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-function-with-addr-output:
  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     (clear-stream _test-error-stream)
  858     (clear-stream $_test-error-buffered-file->buffer)
  859     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  860     68/push 0/imm32
  861     68/push 0/imm32
  862     89/<- %edx 4/r32/esp
  863     (tailor-exit-descriptor %edx 0x10)
  864     #
  865     (write _test-input-stream "fn foo -> _/eax: (addr int) {\n")
  866     (write _test-input-stream "}\n")
  867     # convert
  868     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  869     # registers except esp clobbered at this point
  870     # restore ed
  871     89/<- %edx 4/r32/esp
  872     (flush _test-output-buffered-file)
  873     (flush _test-error-buffered-file)
  874 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
  880     # check output
  881     (check-stream-equal _test-output-stream  ""  "F - test-function-with-addr-output: output should be empty")
  882     (check-next-stream-line-equal _test-error-stream  "fn foo: output cannot have an addr type; that could allow unsafe addresses to escape the function"  "F - test-function-with-addr-output: error message")
  883     # check that stop(1) was called
  884     (check-ints-equal *(edx+4) 2 "F - test-function-with-addr-output: exit status")
  885     # don't restore from ebp
  886     81 0/subop/add %esp 8/imm32
  887     # . epilogue
  888     5d/pop-to-ebp
  889     c3/return
  890 
  891 test-function-with-addr-inout:
  892     # . prologue
  893     55/push-ebp
  894     89/<- %ebp 4/r32/esp
  895     # setup
  896     (clear-stream _test-input-stream)
  897     (clear-stream $_test-input-buffered-file->buffer)
  898     (clear-stream _test-output-stream)
  899     (clear-stream $_test-output-buffered-file->buffer)
  900     (clear-stream _test-error-stream)
  901     (clear-stream $_test-error-buffered-file->buffer)
  902     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  903     68/push 0/imm32
  904     68/push 0/imm32
  905     89/<- %edx 4/r32/esp
  906     (tailor-exit-descriptor %edx 0x10)
  907     #
  908     (write _test-input-stream "fn foo a: (addr addr int) {\n")
  909     (write _test-input-stream "}\n")
  910     # convert
  911     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  912     # registers except esp clobbered at this point
  913     # restore ed
  914     89/<- %edx 4/r32/esp
  915     (flush _test-output-buffered-file)
  916     (flush _test-error-buffered-file)
  917 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
  923     # check output
  924     (check-stream-equal _test-output-stream  ""  "F - test-function-with-addr-inout: output should be empty")
  925     (check-next-stream-line-equal _test-error-stream  "fn foo: inout 'a' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function"  "F - test-function-with-addr-inout: error message")
  926     # check that stop(1) was called
  927     (check-ints-equal *(edx+4) 2 "F - test-function-with-addr-inout: exit status")
  928     # don't restore from ebp
  929     81 0/subop/add %esp 8/imm32
  930     # . epilogue
  931     5d/pop-to-ebp
  932     c3/return
  933 
  934 test-function-with-addr-inout-2:
  935     # . prologue
  936     55/push-ebp
  937     89/<- %ebp 4/r32/esp
  938     # setup
  939     (clear-stream _test-input-stream)
  940     (clear-stream $_test-input-buffered-file->buffer)
  941     (clear-stream _test-output-stream)
  942     (clear-stream $_test-output-buffered-file->buffer)
  943     (clear-stream _test-error-stream)
  944     (clear-stream $_test-error-buffered-file->buffer)
  945     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  946     68/push 0/imm32
  947     68/push 0/imm32
  948     89/<- %edx 4/r32/esp
  949     (tailor-exit-descriptor %edx 0x10)
  950     #
  951     (write _test-input-stream "fn foo a: (addr array addr int) {\n")
  952     (write _test-input-stream "}\n")
  953     # convert
  954     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  955     # registers except esp clobbered at this point
  956     # restore ed
  957     89/<- %edx 4/r32/esp
  958     (flush _test-output-buffered-file)
  959     (flush _test-error-buffered-file)
  960 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
  966     # check output
  967     (check-stream-equal _test-output-stream  ""  "F - test-function-with-addr-inout-2: output should be empty")
  968     (check-next-stream-line-equal _test-error-stream  "fn foo: inout 'a' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function"  "F - test-function-with-addr-inout-2: error message")
  969     # check that stop(1) was called
  970     (check-ints-equal *(edx+4) 2 "F - test-function-with-addr-inout-2: exit status")
  971     # don't restore from ebp
  972     81 0/subop/add %esp 8/imm32
  973     # . epilogue
  974     5d/pop-to-ebp
  975     c3/return
  976 
  977 test-function-with-addr-inout-3:
  978     # . prologue
  979     55/push-ebp
  980     89/<- %ebp 4/r32/esp
  981     # setup
  982     (clear-stream _test-input-stream)
  983     (clear-stream $_test-input-buffered-file->buffer)
  984     (clear-stream _test-output-stream)
  985     (clear-stream $_test-output-buffered-file->buffer)
  986     (clear-stream _test-error-stream)
  987     (clear-stream $_test-error-buffered-file->buffer)
  988     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  989     68/push 0/imm32
  990     68/push 0/imm32
  991     89/<- %edx 4/r32/esp
  992     (tailor-exit-descriptor %edx 0x10)
  993     #
  994     (write _test-input-stream "fn foo a: (addr array (addr int) 3) {\n")
  995     (write _test-input-stream "}\n")
  996     # convert
  997     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  998     # registers except esp clobbered at this point
  999     # restore ed
 1000     89/<- %edx 4/r32/esp
 1001     (flush _test-output-buffered-file)
 1002     (flush _test-error-buffered-file)
 1003 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1009     # check output
 1010     (check-stream-equal _test-output-stream  ""  "F - test-function-with-addr-inout-3: output should be empty")
 1011     (check-next-stream-line-equal _test-error-stream  "fn foo: inout 'a' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function"  "F - test-function-with-addr-inout-3: error message")
 1012     # check that stop(1) was called
 1013     (check-ints-equal *(edx+4) 2 "F - test-function-with-addr-inout-3: exit status")
 1014     # don't restore from ebp
 1015     81 0/subop/add %esp 8/imm32
 1016     # . epilogue
 1017     5d/pop-to-ebp
 1018     c3/return
 1019 
 1020 test-function-with-addr-inout-4:
 1021     # . prologue
 1022     55/push-ebp
 1023     89/<- %ebp 4/r32/esp
 1024     # setup
 1025     (clear-stream _test-input-stream)
 1026     (clear-stream $_test-input-buffered-file->buffer)
 1027     (clear-stream _test-output-stream)
 1028     (clear-stream $_test-output-buffered-file->buffer)
 1029     (clear-stream _test-error-stream)
 1030     (clear-stream $_test-error-buffered-file->buffer)
 1031     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1032     68/push 0/imm32
 1033     68/push 0/imm32
 1034     89/<- %edx 4/r32/esp
 1035     (tailor-exit-descriptor %edx 0x10)
 1036     #
 1037     (write _test-input-stream "fn foo a: (array (addr int) 3) {\n")
 1038     (write _test-input-stream "}\n")
 1039     # convert
 1040     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1041     # registers except esp clobbered at this point
 1042     # restore ed
 1043     89/<- %edx 4/r32/esp
 1044     (flush _test-output-buffered-file)
 1045     (flush _test-error-buffered-file)
 1046 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1052     # check output
 1053     (check-stream-equal _test-output-stream  ""  "F - test-function-with-addr-inout-4: output should be empty")
 1054     (check-next-stream-line-equal _test-error-stream  "fn foo: inout 'a' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function"  "F - test-function-with-addr-inout-4: error message")
 1055     # check that stop(1) was called
 1056     (check-ints-equal *(edx+4) 2 "F - test-function-with-addr-inout-4: exit status")
 1057     # don't restore from ebp
 1058     81 0/subop/add %esp 8/imm32
 1059     # . epilogue
 1060     5d/pop-to-ebp
 1061     c3/return
 1062 
 1063 # 'main' is an exception
 1064 test-function-main-with-addr-inout:
 1065     # . prologue
 1066     55/push-ebp
 1067     89/<- %ebp 4/r32/esp
 1068     # setup
 1069     (clear-stream _test-input-stream)
 1070     (clear-stream $_test-input-buffered-file->buffer)
 1071     (clear-stream _test-output-stream)
 1072     (clear-stream $_test-output-buffered-file->buffer)
 1073     #
 1074     (write _test-input-stream "fn main a: (addr addr int) {\n")
 1075     (write _test-input-stream "}\n")
 1076     # convert
 1077     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1078     (flush _test-output-buffered-file)
 1079     # no errors
 1080     # . epilogue
 1081     89/<- %esp 5/r32/ebp
 1082     5d/pop-to-ebp
 1083     c3/return
 1084 
 1085 # 'lookup' is an exception, but only in signatures
 1086 test-signature-lookup-with-addr-inout:
 1087     # . prologue
 1088     55/push-ebp
 1089     89/<- %ebp 4/r32/esp
 1090     # setup
 1091     (clear-stream _test-input-stream)
 1092     (clear-stream $_test-input-buffered-file->buffer)
 1093     (clear-stream _test-output-stream)
 1094     (clear-stream $_test-output-buffered-file->buffer)
 1095     #
 1096     (write _test-input-stream "sig lookup h: (handle _T) -> _/eax: (addr _T)\n")
 1097     # convert
 1098     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1099     (flush _test-output-buffered-file)
 1100     # no errors
 1101     # . epilogue
 1102     89/<- %esp 5/r32/ebp
 1103     5d/pop-to-ebp
 1104     c3/return
 1105 
 1106 test-convert-function-with-arg-and-body:
 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     #
 1116     (write _test-input-stream "fn foo n: int {\n")
 1117     (write _test-input-stream "  increment n\n")
 1118     (write _test-input-stream "}\n")
 1119     # convert
 1120     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1121     (flush _test-output-buffered-file)
 1122 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 1128     # check output
 1129     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-arg-and-body/0")
 1130     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-arg-and-body/1")
 1131     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-arg-and-body/2")
 1132     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-arg-and-body/3")
 1133     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-arg-and-body/4")
 1134     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-arg-and-body/5")
 1135     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *(ebp+0x00000008)"  "F - test-convert-function-with-arg-and-body/6")
 1136     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-arg-and-body/7")
 1137     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-arg-and-body/8")
 1138     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-arg-and-body/9")
 1139     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-arg-and-body/10")
 1140     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-arg-and-body/11")
 1141     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-arg-and-body/12")
 1142     # . epilogue
 1143     89/<- %esp 5/r32/ebp
 1144     5d/pop-to-ebp
 1145     c3/return
 1146 
 1147 test-convert-function-distinguishes-args:
 1148     # . prologue
 1149     55/push-ebp
 1150     89/<- %ebp 4/r32/esp
 1151     # setup
 1152     (clear-stream _test-input-stream)
 1153     (clear-stream $_test-input-buffered-file->buffer)
 1154     (clear-stream _test-output-stream)
 1155     (clear-stream $_test-output-buffered-file->buffer)
 1156     #
 1157     (write _test-input-stream "fn foo a: int, b: int {\n")
 1158     (write _test-input-stream "  increment b\n")
 1159     (write _test-input-stream "}\n")
 1160     # convert
 1161     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1162     (flush _test-output-buffered-file)
 1163 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 1169     # check output
 1170     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-distinguishes-args/0")
 1171     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-distinguishes-args/1")
 1172     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-distinguishes-args/2")
 1173     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-distinguishes-args/3")
 1174     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-distinguishes-args/4")
 1175     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-distinguishes-args/5")
 1176     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *(ebp+0x0000000c)"  "F - test-convert-function-distinguishes-args/6")
 1177     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-distinguishes-args/7")
 1178     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-distinguishes-args/8")
 1179     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-distinguishes-args/9")
 1180     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-distinguishes-args/10")
 1181     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-distinguishes-args/11")
 1182     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-distinguishes-args/12")
 1183     # . epilogue
 1184     89/<- %esp 5/r32/ebp
 1185     5d/pop-to-ebp
 1186     c3/return
 1187 
 1188 test-convert-function-with-return-literal:
 1189     # . prologue
 1190     55/push-ebp
 1191     89/<- %ebp 4/r32/esp
 1192     # setup
 1193     (clear-stream _test-input-stream)
 1194     (clear-stream $_test-input-buffered-file->buffer)
 1195     (clear-stream _test-output-stream)
 1196     (clear-stream $_test-output-buffered-file->buffer)
 1197     #
 1198     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1199     (write _test-input-stream "  return 0\n")
 1200     (write _test-input-stream "}\n")
 1201     # convert
 1202     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1203     (flush _test-output-buffered-file)
 1204 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 1210     # check output
 1211     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-literal/0")
 1212     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-literal/1")
 1213     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-literal/2")
 1214     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-literal/3")
 1215     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-literal/4")
 1216     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-literal/5")
 1217     (check-next-stream-line-equal _test-output-stream "    c7 0/subop/copy %eax 0/imm32"  "F - test-convert-function-with-return-literal/6")
 1218     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-literal/7")
 1219     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-literal/8")
 1220     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-literal/9")
 1221     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-literal/10")
 1222     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-literal/11")
 1223     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-literal/12")
 1224     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-literal/13")
 1225     # . epilogue
 1226     89/<- %esp 5/r32/ebp
 1227     5d/pop-to-ebp
 1228     c3/return
 1229 
 1230 test-convert-function-with-return:
 1231     # . prologue
 1232     55/push-ebp
 1233     89/<- %ebp 4/r32/esp
 1234     # setup
 1235     (clear-stream _test-input-stream)
 1236     (clear-stream $_test-input-buffered-file->buffer)
 1237     (clear-stream _test-output-stream)
 1238     (clear-stream $_test-output-buffered-file->buffer)
 1239     #
 1240     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1241     (write _test-input-stream "  var y: int\n")
 1242     (write _test-input-stream "  return y\n")
 1243     (write _test-input-stream "}\n")
 1244     # convert
 1245     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1246     (flush _test-output-buffered-file)
 1247 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 1253     # check output
 1254     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return/0")
 1255     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return/1")
 1256     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return/2")
 1257     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return/3")
 1258     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return/4")
 1259     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return/5")
 1260     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-return/6")  # y
 1261     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0xfffffffc) 0x00000000/r32" "F - test-convert-function-with-return/7")
 1262     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-return/8")
 1263     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return/9")
 1264     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return/10")
 1265     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return/11")
 1266     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return/12")
 1267     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return/13")
 1268     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return/14")
 1269     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return/15")
 1270     # . epilogue
 1271     89/<- %esp 5/r32/ebp
 1272     5d/pop-to-ebp
 1273     c3/return
 1274 
 1275 test-convert-function-with-return-float:
 1276     # . prologue
 1277     55/push-ebp
 1278     89/<- %ebp 4/r32/esp
 1279     # setup
 1280     (clear-stream _test-input-stream)
 1281     (clear-stream $_test-input-buffered-file->buffer)
 1282     (clear-stream _test-output-stream)
 1283     (clear-stream $_test-output-buffered-file->buffer)
 1284     #
 1285     (write _test-input-stream "fn foo -> _/xmm0: float {\n")
 1286     (write _test-input-stream "  var y: float\n")
 1287     (write _test-input-stream "  return y\n")
 1288     (write _test-input-stream "}\n")
 1289     # convert
 1290     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1291     (flush _test-output-buffered-file)
 1292 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 1298     # check output
 1299     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return/0")
 1300     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return/1")
 1301     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return/2")
 1302     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return/3")
 1303     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return/4")
 1304     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return/5")
 1305     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-return/6")  # y
 1306     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *(ebp+0xfffffffc) 0x00000000/x32" "F - test-convert-function-with-return/7")
 1307     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-return/8")
 1308     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return/9")
 1309     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return/10")
 1310     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return/11")
 1311     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return/12")
 1312     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return/13")
 1313     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return/14")
 1314     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return/15")
 1315     # . epilogue
 1316     89/<- %esp 5/r32/ebp
 1317     5d/pop-to-ebp
 1318     c3/return
 1319 
 1320 test-convert-function-with-return-register:
 1321     # . prologue
 1322     55/push-ebp
 1323     89/<- %ebp 4/r32/esp
 1324     # setup
 1325     (clear-stream _test-input-stream)
 1326     (clear-stream $_test-input-buffered-file->buffer)
 1327     (clear-stream _test-output-stream)
 1328     (clear-stream $_test-output-buffered-file->buffer)
 1329     #
 1330     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1331     (write _test-input-stream "  var y/eax: int <- copy 3\n")
 1332     (write _test-input-stream "  return y\n")
 1333     (write _test-input-stream "}\n")
 1334     # convert
 1335     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1336     (flush _test-output-buffered-file)
 1337 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 1343     # check output
 1344     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-register/0")
 1345     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-register/1")
 1346     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-register/2")
 1347     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-register/3")
 1348     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-register/4")
 1349     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-register/5")
 1350     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-with-return-register/6")
 1351     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 3/imm32"  "F - test-convert-function-with-return-register/7")
 1352     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32" "F - test-convert-function-with-return-register/8")
 1353     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-with-return-register/9")
 1354     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-register/10")
 1355     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-register/11")
 1356     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-register/12")
 1357     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-register/13")
 1358     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-register/14")
 1359     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-register/15")
 1360     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-register/16")
 1361     # . epilogue
 1362     89/<- %esp 5/r32/ebp
 1363     5d/pop-to-ebp
 1364     c3/return
 1365 
 1366 test-function-with-output-without-register:
 1367     # . prologue
 1368     55/push-ebp
 1369     89/<- %ebp 4/r32/esp
 1370     # setup
 1371     (clear-stream _test-input-stream)
 1372     (clear-stream $_test-input-buffered-file->buffer)
 1373     (clear-stream _test-output-stream)
 1374     (clear-stream $_test-output-buffered-file->buffer)
 1375     (clear-stream _test-error-stream)
 1376     (clear-stream $_test-error-buffered-file->buffer)
 1377     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1378     68/push 0/imm32
 1379     68/push 0/imm32
 1380     89/<- %edx 4/r32/esp
 1381     (tailor-exit-descriptor %edx 0x10)
 1382     #
 1383     (write _test-input-stream "fn foo -> _: int {\n")
 1384     (write _test-input-stream "}\n")
 1385     # convert
 1386     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1387     # registers except esp clobbered at this point
 1388     # restore ed
 1389     89/<- %edx 4/r32/esp
 1390     (flush _test-output-buffered-file)
 1391     (flush _test-error-buffered-file)
 1392 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1398     # check output
 1399     (check-stream-equal _test-output-stream  ""  "F - test-function-with-output-without-register: output should be empty")
 1400     (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")
 1401     # check that stop(1) was called
 1402     (check-ints-equal *(edx+4) 2 "F - test-function-with-output-without-register: exit status")
 1403     # don't restore from ebp
 1404     81 0/subop/add %esp 8/imm32
 1405     # . epilogue
 1406     5d/pop-to-ebp
 1407     c3/return
 1408 
 1409 test-function-with-outputs-in-conflicting-registers:
 1410     # . prologue
 1411     55/push-ebp
 1412     89/<- %ebp 4/r32/esp
 1413     # setup
 1414     (clear-stream _test-input-stream)
 1415     (clear-stream $_test-input-buffered-file->buffer)
 1416     (clear-stream _test-output-stream)
 1417     (clear-stream $_test-output-buffered-file->buffer)
 1418     (clear-stream _test-error-stream)
 1419     (clear-stream $_test-error-buffered-file->buffer)
 1420     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1421     68/push 0/imm32
 1422     68/push 0/imm32
 1423     89/<- %edx 4/r32/esp
 1424     (tailor-exit-descriptor %edx 0x10)
 1425     #
 1426     (write _test-input-stream "fn foo -> _/eax: int, _/eax: int {\n")
 1427     (write _test-input-stream "}\n")
 1428     # convert
 1429     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1430     # registers except esp clobbered at this point
 1431     # restore ed
 1432     89/<- %edx 4/r32/esp
 1433     (flush _test-output-buffered-file)
 1434     (flush _test-error-buffered-file)
 1435 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1441     # check output
 1442     (check-stream-equal _test-output-stream  ""  "F - test-function-with-outputs-in-conflicting-registers: output should be empty")
 1443     (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")
 1444     # check that stop(1) was called
 1445     (check-ints-equal *(edx+4) 2 "F - test-function-with-outputs-in-conflicting-registers: exit status")
 1446     # don't restore from ebp
 1447     81 0/subop/add %esp 8/imm32
 1448     # . epilogue
 1449     5d/pop-to-ebp
 1450     c3/return
 1451 
 1452 test-function-with-named-output:
 1453     # . prologue
 1454     55/push-ebp
 1455     89/<- %ebp 4/r32/esp
 1456     # setup
 1457     (clear-stream _test-input-stream)
 1458     (clear-stream $_test-input-buffered-file->buffer)
 1459     (clear-stream _test-output-stream)
 1460     (clear-stream $_test-output-buffered-file->buffer)
 1461     (clear-stream _test-error-stream)
 1462     (clear-stream $_test-error-buffered-file->buffer)
 1463     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1464     68/push 0/imm32
 1465     68/push 0/imm32
 1466     89/<- %edx 4/r32/esp
 1467     (tailor-exit-descriptor %edx 0x10)
 1468     #
 1469     (write _test-input-stream "fn foo -> x/eax: int {\n")
 1470     (write _test-input-stream "  return 0\n")
 1471     (write _test-input-stream "}\n")
 1472     # convert
 1473     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1474     # registers except esp clobbered at this point
 1475     # restore ed
 1476     89/<- %edx 4/r32/esp
 1477     (flush _test-output-buffered-file)
 1478     (flush _test-error-buffered-file)
 1479 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1485     # check output
 1486     (check-stream-equal _test-output-stream  ""  "F - test-function-with-named-output: output should be empty")
 1487     (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")
 1488     # check that stop(1) was called
 1489     (check-ints-equal *(edx+4) 2 "F - test-function-with-named-output: exit status")
 1490     # don't restore from ebp
 1491     81 0/subop/add %esp 8/imm32
 1492     # . epilogue
 1493     5d/pop-to-ebp
 1494     c3/return
 1495 
 1496 test-return-with-wrong-type:
 1497     # . prologue
 1498     55/push-ebp
 1499     89/<- %ebp 4/r32/esp
 1500     # setup
 1501     (clear-stream _test-input-stream)
 1502     (clear-stream $_test-input-buffered-file->buffer)
 1503     (clear-stream _test-output-stream)
 1504     (clear-stream $_test-output-buffered-file->buffer)
 1505     (clear-stream _test-error-stream)
 1506     (clear-stream $_test-error-buffered-file->buffer)
 1507     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1508     68/push 0/imm32
 1509     68/push 0/imm32
 1510     89/<- %edx 4/r32/esp
 1511     (tailor-exit-descriptor %edx 0x10)
 1512     #
 1513     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1514     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
 1515     (write _test-input-stream "  return x\n")
 1516     (write _test-input-stream "}\n")
 1517     # convert
 1518     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1519     # registers except esp clobbered at this point
 1520     # restore ed
 1521     89/<- %edx 4/r32/esp
 1522     (flush _test-output-buffered-file)
 1523     (flush _test-error-buffered-file)
 1524 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1530     # check output
 1531     (check-stream-equal _test-output-stream  ""  "F - test-return-with-wrong-type: output should be empty")
 1532     (check-next-stream-line-equal _test-error-stream  "fn foo: return: 'x' has the wrong type"  "F - test-return-with-wrong-type: error message")
 1533     # check that stop(1) was called
 1534     (check-ints-equal *(edx+4) 2 "F - test-return-with-wrong-type: exit status")
 1535     # don't restore from ebp
 1536     81 0/subop/add %esp 8/imm32
 1537     # . epilogue
 1538     5d/pop-to-ebp
 1539     c3/return
 1540 
 1541 test-missing-return:
 1542     # . prologue
 1543     55/push-ebp
 1544     89/<- %ebp 4/r32/esp
 1545     # setup
 1546     (clear-stream _test-input-stream)
 1547     (clear-stream $_test-input-buffered-file->buffer)
 1548     (clear-stream _test-output-stream)
 1549     (clear-stream $_test-output-buffered-file->buffer)
 1550     (clear-stream _test-error-stream)
 1551     (clear-stream $_test-error-buffered-file->buffer)
 1552     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1553     68/push 0/imm32
 1554     68/push 0/imm32
 1555     89/<- %edx 4/r32/esp
 1556     (tailor-exit-descriptor %edx 0x10)
 1557     #
 1558     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1559     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
 1560     (write _test-input-stream "}\n")
 1561     # convert
 1562     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1563     # registers except esp clobbered at this point
 1564     # restore ed
 1565     89/<- %edx 4/r32/esp
 1566     (flush _test-output-buffered-file)
 1567     (flush _test-error-buffered-file)
 1568 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1574     # check output
 1575     (check-stream-equal _test-output-stream  ""  "F - test-missing-return: output should be empty")
 1576     (check-next-stream-line-equal _test-error-stream  "fn foo: final statement should be a 'return'"  "F - test-missing-return: error message")
 1577     # check that stop(1) was called
 1578     (check-ints-equal *(edx+4) 2 "F - test-missing-return: exit status")
 1579     # don't restore from ebp
 1580     81 0/subop/add %esp 8/imm32
 1581     # . epilogue
 1582     5d/pop-to-ebp
 1583     c3/return
 1584 
 1585 test-missing-return-2:
 1586     # . prologue
 1587     55/push-ebp
 1588     89/<- %ebp 4/r32/esp
 1589     # setup
 1590     (clear-stream _test-input-stream)
 1591     (clear-stream $_test-input-buffered-file->buffer)
 1592     (clear-stream _test-output-stream)
 1593     (clear-stream $_test-output-buffered-file->buffer)
 1594     (clear-stream _test-error-stream)
 1595     (clear-stream $_test-error-buffered-file->buffer)
 1596     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1597     68/push 0/imm32
 1598     68/push 0/imm32
 1599     89/<- %edx 4/r32/esp
 1600     (tailor-exit-descriptor %edx 0x10)
 1601     #
 1602     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1603     (write _test-input-stream "}\n")
 1604     # convert
 1605     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1606     # registers except esp clobbered at this point
 1607     # restore ed
 1608     89/<- %edx 4/r32/esp
 1609     (flush _test-output-buffered-file)
 1610     (flush _test-error-buffered-file)
 1611 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1617     # check output
 1618     (check-stream-equal _test-output-stream  ""  "F - test-missing-return-2: output should be empty")
 1619     (check-next-stream-line-equal _test-error-stream  "fn foo: final statement should be a 'return'"  "F - test-missing-return-2: error message")
 1620     # check that stop(1) was called
 1621     (check-ints-equal *(edx+4) 2 "F - test-missing-return-2: exit status")
 1622     # don't restore from ebp
 1623     81 0/subop/add %esp 8/imm32
 1624     # . epilogue
 1625     5d/pop-to-ebp
 1626     c3/return
 1627 
 1628 test-early-exit-without-return:
 1629     # . prologue
 1630     55/push-ebp
 1631     89/<- %ebp 4/r32/esp
 1632     # setup
 1633     (clear-stream _test-input-stream)
 1634     (clear-stream $_test-input-buffered-file->buffer)
 1635     (clear-stream _test-output-stream)
 1636     (clear-stream $_test-output-buffered-file->buffer)
 1637     (clear-stream _test-error-stream)
 1638     (clear-stream $_test-error-buffered-file->buffer)
 1639     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1640     68/push 0/imm32
 1641     68/push 0/imm32
 1642     89/<- %edx 4/r32/esp
 1643     (tailor-exit-descriptor %edx 0x10)
 1644     #
 1645     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1646     (write _test-input-stream "  break\n")
 1647     (write _test-input-stream "  return 0\n")
 1648     (write _test-input-stream "}\n")
 1649     # convert
 1650     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1651     # registers except esp clobbered at this point
 1652     # restore ed
 1653     89/<- %edx 4/r32/esp
 1654     (flush _test-output-buffered-file)
 1655     (flush _test-error-buffered-file)
 1656 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1662     # check output
 1663     (check-stream-equal _test-output-stream  ""  "F - test-early-exit-without-return: output should be empty")
 1664     (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")
 1665     # check that stop(1) was called
 1666     (check-ints-equal *(edx+4) 2 "F - test-early-exit-without-return: exit status")
 1667     # don't restore from ebp
 1668     81 0/subop/add %esp 8/imm32
 1669     # . epilogue
 1670     5d/pop-to-ebp
 1671     c3/return
 1672 
 1673 test-return-with-too-few-inouts:
 1674     # . prologue
 1675     55/push-ebp
 1676     89/<- %ebp 4/r32/esp
 1677     # setup
 1678     (clear-stream _test-input-stream)
 1679     (clear-stream $_test-input-buffered-file->buffer)
 1680     (clear-stream _test-output-stream)
 1681     (clear-stream $_test-output-buffered-file->buffer)
 1682     (clear-stream _test-error-stream)
 1683     (clear-stream $_test-error-buffered-file->buffer)
 1684     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1685     68/push 0/imm32
 1686     68/push 0/imm32
 1687     89/<- %edx 4/r32/esp
 1688     (tailor-exit-descriptor %edx 0x10)
 1689     #
 1690     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1691     (write _test-input-stream "  return\n")
 1692     (write _test-input-stream "}\n")
 1693     # convert
 1694     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1695     # registers except esp clobbered at this point
 1696     # restore ed
 1697     89/<- %edx 4/r32/esp
 1698     (flush _test-output-buffered-file)
 1699     (flush _test-error-buffered-file)
 1700 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1706     # check output
 1707     (check-stream-equal _test-output-stream  ""  "F - test-return-with-too-few-inouts: output should be empty")
 1708     (check-next-stream-line-equal _test-error-stream  "fn foo: return: too few inouts"  "F - test-return-with-too-few-inouts: error message")
 1709     # check that stop(1) was called
 1710     (check-ints-equal *(edx+4) 2 "F - test-return-with-too-few-inouts: exit status")
 1711     # don't restore from ebp
 1712     81 0/subop/add %esp 8/imm32
 1713     # . epilogue
 1714     5d/pop-to-ebp
 1715     c3/return
 1716 
 1717 test-return-with-too-many-inouts:
 1718     # . prologue
 1719     55/push-ebp
 1720     89/<- %ebp 4/r32/esp
 1721     # setup
 1722     (clear-stream _test-input-stream)
 1723     (clear-stream $_test-input-buffered-file->buffer)
 1724     (clear-stream _test-output-stream)
 1725     (clear-stream $_test-output-buffered-file->buffer)
 1726     (clear-stream _test-error-stream)
 1727     (clear-stream $_test-error-buffered-file->buffer)
 1728     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1729     68/push 0/imm32
 1730     68/push 0/imm32
 1731     89/<- %edx 4/r32/esp
 1732     (tailor-exit-descriptor %edx 0x10)
 1733     #
 1734     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1735     (write _test-input-stream "  return 0, 0\n")
 1736     (write _test-input-stream "}\n")
 1737     # convert
 1738     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1739     # registers except esp clobbered at this point
 1740     # restore ed
 1741     89/<- %edx 4/r32/esp
 1742     (flush _test-output-buffered-file)
 1743     (flush _test-error-buffered-file)
 1744 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1750     # check output
 1751     (check-stream-equal _test-output-stream  ""  "F - test-return-with-too-many-inouts: output should be empty")
 1752     (check-next-stream-line-equal _test-error-stream  "fn foo: return: too many inouts"  "F - test-return-with-too-many-inouts: error message")
 1753     # check that stop(1) was called
 1754     (check-ints-equal *(edx+4) 2 "F - test-return-with-too-many-inouts: exit status")
 1755     # don't restore from ebp
 1756     81 0/subop/add %esp 8/imm32
 1757     # . epilogue
 1758     5d/pop-to-ebp
 1759     c3/return
 1760 
 1761 test-return-unavailable-value:
 1762     # . prologue
 1763     55/push-ebp
 1764     89/<- %ebp 4/r32/esp
 1765     # setup
 1766     (clear-stream _test-input-stream)
 1767     (clear-stream $_test-input-buffered-file->buffer)
 1768     (clear-stream _test-output-stream)
 1769     (clear-stream $_test-output-buffered-file->buffer)
 1770     (clear-stream _test-error-stream)
 1771     (clear-stream $_test-error-buffered-file->buffer)
 1772     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1773     68/push 0/imm32
 1774     68/push 0/imm32
 1775     89/<- %edx 4/r32/esp
 1776     (tailor-exit-descriptor %edx 0x10)
 1777     #
 1778     (write _test-input-stream "fn foo -> _/eax: int, _/ecx: int {\n")
 1779     (write _test-input-stream "  var x/eax: int <- copy 0\n")
 1780     (write _test-input-stream "  var y/ecx: int <- copy 0\n")
 1781     (write _test-input-stream "  return y, x\n")
 1782     (write _test-input-stream "}\n")
 1783     # convert
 1784     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1785     # registers except esp clobbered at this point
 1786     # restore ed
 1787     89/<- %edx 4/r32/esp
 1788     (flush _test-output-buffered-file)
 1789     (flush _test-error-buffered-file)
 1790 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1796     # check output
 1797     (check-stream-equal _test-output-stream  ""  "F - test-return-unavailable-value: output should be empty")
 1798     (check-next-stream-line-equal _test-error-stream  "fn foo: return: 'x' is no longer available"  "F - test-return-unavailable-value: error message")
 1799     # check that stop(1) was called
 1800     (check-ints-equal *(edx+4) 2 "F - test-return-unavailable-value: exit status")
 1801     # don't restore from ebp
 1802     81 0/subop/add %esp 8/imm32
 1803     # . epilogue
 1804     5d/pop-to-ebp
 1805     c3/return
 1806 
 1807 test-return-literal-to-float:
 1808     # . prologue
 1809     55/push-ebp
 1810     89/<- %ebp 4/r32/esp
 1811     # setup
 1812     (clear-stream _test-input-stream)
 1813     (clear-stream $_test-input-buffered-file->buffer)
 1814     (clear-stream _test-output-stream)
 1815     (clear-stream $_test-output-buffered-file->buffer)
 1816     (clear-stream _test-error-stream)
 1817     (clear-stream $_test-error-buffered-file->buffer)
 1818     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1819     68/push 0/imm32
 1820     68/push 0/imm32
 1821     89/<- %edx 4/r32/esp
 1822     (tailor-exit-descriptor %edx 0x10)
 1823     #
 1824     (write _test-input-stream "fn foo -> _/xmm0: float {\n")
 1825     (write _test-input-stream "  return 0\n")
 1826     (write _test-input-stream "}\n")
 1827     # convert
 1828     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1829     # registers except esp clobbered at this point
 1830     # restore ed
 1831     89/<- %edx 4/r32/esp
 1832     (flush _test-output-buffered-file)
 1833     (flush _test-error-buffered-file)
 1834 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1840     # check output
 1841     (check-stream-equal _test-output-stream  ""  "F - test-return-literal-to-float: output should be empty")
 1842     (check-next-stream-line-equal _test-error-stream  "fn foo: return: cannot copy literal '0' to float"  "F - test-return-literal-to-float: error message")
 1843     # check that stop(1) was called
 1844     (check-ints-equal *(edx+4) 2 "F - test-return-literal-to-float: exit status")
 1845     # don't restore from ebp
 1846     81 0/subop/add %esp 8/imm32
 1847     # . epilogue
 1848     5d/pop-to-ebp
 1849     c3/return
 1850 
 1851 test-convert-return-with-duplicate-values:
 1852     # . prologue
 1853     55/push-ebp
 1854     89/<- %ebp 4/r32/esp
 1855     # setup
 1856     (clear-stream _test-input-stream)
 1857     (clear-stream $_test-input-buffered-file->buffer)
 1858     (clear-stream _test-output-stream)
 1859     (clear-stream $_test-output-buffered-file->buffer)
 1860     #
 1861     (write _test-input-stream "fn foo -> _/eax: int, _/ecx: int {\n")
 1862     (write _test-input-stream "  var x/eax: int <- copy 0x34\n")
 1863     (write _test-input-stream "  return x, x\n")
 1864     (write _test-input-stream "}\n")
 1865     # convert
 1866     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1867     (flush _test-output-buffered-file)
 1868 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 1874     # check output
 1875     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-return-with-duplicate-values/0")
 1876     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-return-with-duplicate-values/1")
 1877     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-return-with-duplicate-values/2")
 1878     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-return-with-duplicate-values/3")
 1879     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-return-with-duplicate-values/4")
 1880     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-return-with-duplicate-values/5")
 1881     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-return-with-duplicate-values/6")
 1882     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0x34/imm32"  "F - test-convert-return-with-duplicate-values/7")
 1883     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32"  "F - test-convert-return-with-duplicate-values/8")
 1884     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000001/r32"  "F - test-convert-return-with-duplicate-values/9")
 1885     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-return-with-duplicate-values/10")
 1886     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-return-with-duplicate-values/11")
 1887     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-return-with-duplicate-values/12")
 1888     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-return-with-duplicate-values/13")
 1889     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-return-with-duplicate-values/14")
 1890     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-return-with-duplicate-values/15")
 1891     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-return-with-duplicate-values/16")
 1892     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-return-with-duplicate-values/17")
 1893     # . epilogue
 1894     89/<- %esp 5/r32/ebp
 1895     5d/pop-to-ebp
 1896     c3/return
 1897 
 1898 test-convert-return-with-duplicate-values-2:
 1899     # . prologue
 1900     55/push-ebp
 1901     89/<- %ebp 4/r32/esp
 1902     # setup
 1903     (clear-stream _test-input-stream)
 1904     (clear-stream $_test-input-buffered-file->buffer)
 1905     (clear-stream _test-output-stream)
 1906     (clear-stream $_test-output-buffered-file->buffer)
 1907     #
 1908     (write _test-input-stream "fn foo -> _/eax: int, _/ecx: int {\n")
 1909     (write _test-input-stream "  var x/ecx: int <- copy 0x34\n")
 1910     (write _test-input-stream "  return x, x\n")
 1911     (write _test-input-stream "}\n")
 1912     # convert
 1913     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1914     (flush _test-output-buffered-file)
 1915 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 1921     # check output
 1922     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-return-with-duplicate-values-2/0")
 1923     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-return-with-duplicate-values-2/1")
 1924     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-return-with-duplicate-values-2/2")
 1925     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-return-with-duplicate-values-2/3")
 1926     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-return-with-duplicate-values-2/4")
 1927     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-return-with-duplicate-values-2/5")
 1928     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-return-with-duplicate-values-2/6")
 1929     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0x34/imm32"  "F - test-convert-return-with-duplicate-values-2/7")
 1930     (check-next-stream-line-equal _test-output-stream "    8b/-> %ecx 0x00000000/r32"  "F - test-convert-return-with-duplicate-values-2/8")
 1931     (check-next-stream-line-equal _test-output-stream "    8b/-> %ecx 0x00000001/r32"  "F - test-convert-return-with-duplicate-values-2/9")
 1932     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-return-with-duplicate-values-2/10")
 1933     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-return-with-duplicate-values-2/11")
 1934     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-return-with-duplicate-values-2/12")
 1935     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-return-with-duplicate-values-2/13")
 1936     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-return-with-duplicate-values-2/14")
 1937     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-return-with-duplicate-values-2/15")
 1938     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-return-with-duplicate-values-2/16")
 1939     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-return-with-duplicate-values-2/17")
 1940     # . epilogue
 1941     89/<- %esp 5/r32/ebp
 1942     5d/pop-to-ebp
 1943     c3/return
 1944 
 1945 test-stmt-with-unknown-var:
 1946     # . prologue
 1947     55/push-ebp
 1948     89/<- %ebp 4/r32/esp
 1949     # setup
 1950     (clear-stream _test-input-stream)
 1951     (clear-stream $_test-input-buffered-file->buffer)
 1952     (clear-stream _test-output-stream)
 1953     (clear-stream $_test-output-buffered-file->buffer)
 1954     (clear-stream _test-error-stream)
 1955     (clear-stream $_test-error-buffered-file->buffer)
 1956     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1957     68/push 0/imm32
 1958     68/push 0/imm32
 1959     89/<- %edx 4/r32/esp
 1960     (tailor-exit-descriptor %edx 0x10)
 1961     #
 1962     (write _test-input-stream "fn foo {\n")
 1963     (write _test-input-stream "  x <- copy 0x34\n")
 1964     (write _test-input-stream "}\n")
 1965     # convert
 1966     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1967     # registers except esp clobbered at this point
 1968     # restore ed
 1969     89/<- %edx 4/r32/esp
 1970     (flush _test-output-buffered-file)
 1971     (flush _test-error-buffered-file)
 1972 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1978     # check output
 1979     (check-stream-equal _test-output-stream  ""  "F - test-stmt-with-unknown-var: output should be empty")
 1980     (check-next-stream-line-equal _test-error-stream  "fn foo: unknown variable 'x'"  "F - test-stmt-with-unknown-var: error message")
 1981     # check that stop(1) was called
 1982     (check-ints-equal *(edx+4) 2 "F - test-stmt-with-unknown-var: exit status")
 1983     # don't restore from ebp
 1984     81 0/subop/add %esp 8/imm32
 1985     # . epilogue
 1986     5d/pop-to-ebp
 1987     c3/return
 1988 
 1989 test-stmt-with-invalid-identifier:
 1990     # . prologue
 1991     55/push-ebp
 1992     89/<- %ebp 4/r32/esp
 1993     # setup
 1994     (clear-stream _test-input-stream)
 1995     (clear-stream $_test-input-buffered-file->buffer)
 1996     (clear-stream _test-output-stream)
 1997     (clear-stream $_test-output-buffered-file->buffer)
 1998     (clear-stream _test-error-stream)
 1999     (clear-stream $_test-error-buffered-file->buffer)
 2000     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2001     68/push 0/imm32
 2002     68/push 0/imm32
 2003     89/<- %edx 4/r32/esp
 2004     (tailor-exit-descriptor %edx 0x10)
 2005     #
 2006     (write _test-input-stream "fn foo {\n")
 2007     (write _test-input-stream "  1 <- copy 0x34\n")
 2008     (write _test-input-stream "}\n")
 2009     # convert
 2010     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2011     # registers except esp clobbered at this point
 2012     # restore ed
 2013     89/<- %edx 4/r32/esp
 2014     (flush _test-output-buffered-file)
 2015     (flush _test-error-buffered-file)
 2016 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2022     # check output
 2023     (check-stream-equal _test-output-stream  ""  "F - test-stmt-with-invalid-identifier: output should be empty")
 2024     (check-next-stream-line-equal _test-error-stream  "fn foo: invalid identifier '1'"  "F - test-stmt-with-invalid-identifier: error message")
 2025     # check that stop(1) was called
 2026     (check-ints-equal *(edx+4) 2 "F - test-stmt-with-invalid-identifier: exit status")
 2027     # don't restore from ebp
 2028     81 0/subop/add %esp 8/imm32
 2029     # . epilogue
 2030     5d/pop-to-ebp
 2031     c3/return
 2032 
 2033 test-stmt-with-deref-var:
 2034     # . prologue
 2035     55/push-ebp
 2036     89/<- %ebp 4/r32/esp
 2037     # setup
 2038     (clear-stream _test-input-stream)
 2039     (clear-stream $_test-input-buffered-file->buffer)
 2040     (clear-stream _test-output-stream)
 2041     (clear-stream $_test-output-buffered-file->buffer)
 2042     (clear-stream _test-error-stream)
 2043     (clear-stream $_test-error-buffered-file->buffer)
 2044     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2045     68/push 0/imm32
 2046     68/push 0/imm32
 2047     89/<- %edx 4/r32/esp
 2048     (tailor-exit-descriptor %edx 0x10)
 2049     #
 2050     (write _test-input-stream "fn foo {\n")
 2051     (write _test-input-stream "  *x <- copy 0x34\n")
 2052     (write _test-input-stream "}\n")
 2053     # convert
 2054     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2055     # registers except esp clobbered at this point
 2056     # restore ed
 2057     89/<- %edx 4/r32/esp
 2058     (flush _test-output-buffered-file)
 2059     (flush _test-error-buffered-file)
 2060 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2066     # check output
 2067     (check-stream-equal _test-output-stream  ""  "F - test-stmt-with-deref-var: output should be empty")
 2068     (check-next-stream-line-equal _test-error-stream  "fn foo: output '*x' should write to a register, and therefore cannot be dereferenced"  "F - test-stmt-with-deref-var: error message")
 2069     # check that stop(1) was called
 2070     (check-ints-equal *(edx+4) 2 "F - test-stmt-with-deref-var: exit status")
 2071     # don't restore from ebp
 2072     81 0/subop/add %esp 8/imm32
 2073     # . epilogue
 2074     5d/pop-to-ebp
 2075     c3/return
 2076 
 2077 test-convert-function-with-literal-arg:
 2078     # . prologue
 2079     55/push-ebp
 2080     89/<- %ebp 4/r32/esp
 2081     # setup
 2082     (clear-stream _test-input-stream)
 2083     (clear-stream $_test-input-buffered-file->buffer)
 2084     (clear-stream _test-output-stream)
 2085     (clear-stream $_test-output-buffered-file->buffer)
 2086     #
 2087     (write _test-input-stream "fn foo a: int, b: int -> _/eax: int {\n")
 2088     (write _test-input-stream "  var result/eax: int <- copy a\n")
 2089     (write _test-input-stream "  result <- add 1\n")
 2090     (write _test-input-stream "  return result\n")
 2091     (write _test-input-stream "}\n")
 2092     # convert
 2093     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2094     (flush _test-output-buffered-file)
 2095 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2101     # check output
 2102     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-literal-arg/0")
 2103     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-literal-arg/1")
 2104     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-literal-arg/2")
 2105     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-literal-arg/3")
 2106     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-literal-arg/4")
 2107     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-literal-arg/5")
 2108     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-with-literal-arg/6")
 2109     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-function-with-literal-arg/7")
 2110     (check-next-stream-line-equal _test-output-stream "    05/add-to-eax 1/imm32"  "F - test-convert-function-with-literal-arg/8")
 2111     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32" "F - test-convert-function-with-literal-arg/9")
 2112     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-with-literal-arg/10")
 2113     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-literal-arg/11")
 2114     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-literal-arg/12")
 2115     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-literal-arg/13")
 2116     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-literal-arg/14")
 2117     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-literal-arg/15")
 2118     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-literal-arg/16")
 2119     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-literal-arg/17")
 2120     # . epilogue
 2121     89/<- %esp 5/r32/ebp
 2122     5d/pop-to-ebp
 2123     c3/return
 2124 
 2125 test-convert-function-with-literal-arg-2:
 2126     # . prologue
 2127     55/push-ebp
 2128     89/<- %ebp 4/r32/esp
 2129     # setup
 2130     (clear-stream _test-input-stream)
 2131     (clear-stream $_test-input-buffered-file->buffer)
 2132     (clear-stream _test-output-stream)
 2133     (clear-stream $_test-output-buffered-file->buffer)
 2134     #
 2135     (write _test-input-stream "fn foo a: int, b: int -> _/ebx: int {\n")
 2136     (write _test-input-stream "  var result/ebx: int <- copy a\n")
 2137     (write _test-input-stream "  result <- add 1\n")
 2138     (write _test-input-stream "  return result\n")
 2139     (write _test-input-stream "}\n")
 2140     # convert
 2141     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2142     (flush _test-output-buffered-file)
 2143 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2149     # check output
 2150     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-literal-arg-2/0")
 2151     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-literal-arg-2/1")
 2152     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-literal-arg-2/2")
 2153     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-literal-arg-2/3")
 2154     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-literal-arg-2/4")
 2155     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-literal-arg-2/5")
 2156     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ebx"  "F - test-convert-function-with-literal-arg-2/6")
 2157     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000003/r32"  "F - test-convert-function-with-literal-arg-2/7")
 2158     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %ebx 1/imm32"  "F - test-convert-function-with-literal-arg-2/8")
 2159     (check-next-stream-line-equal _test-output-stream "    8b/-> %ebx 0x00000003/r32" "F - test-convert-function-with-literal-arg-2/9")
 2160     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-with-literal-arg-2/10")
 2161     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-literal-arg-2/11")
 2162     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-literal-arg-2/12")
 2163     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-literal-arg-2/13")
 2164     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-literal-arg-2/14")
 2165     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-literal-arg-2/15")
 2166     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-literal-arg-2/16")
 2167     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-literal-arg-2/17")
 2168     # . epilogue
 2169     89/<- %esp 5/r32/ebp
 2170     5d/pop-to-ebp
 2171     c3/return
 2172 
 2173 test-convert-function-call-with-literal-arg:
 2174     # . prologue
 2175     55/push-ebp
 2176     89/<- %ebp 4/r32/esp
 2177     # setup
 2178     (clear-stream _test-input-stream)
 2179     (clear-stream $_test-input-buffered-file->buffer)
 2180     (clear-stream _test-output-stream)
 2181     (clear-stream $_test-output-buffered-file->buffer)
 2182     #
 2183     (write _test-input-stream "fn main -> _/ebx: int {\n")
 2184     (write _test-input-stream "  var result/eax: int <- do-add 3 4\n")
 2185     (write _test-input-stream "  return result\n")
 2186     (write _test-input-stream "}\n")
 2187     (write _test-input-stream "fn do-add a: int, b: int -> _/eax: int {\n")
 2188     (write _test-input-stream "  var result/eax: int <- copy a\n")
 2189     (write _test-input-stream "  result <- add b\n")
 2190     (write _test-input-stream "  return result\n")
 2191     (write _test-input-stream "}\n")
 2192     # convert
 2193     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2194     (flush _test-output-buffered-file)
 2195 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2201     # check output
 2202     (check-next-stream-line-equal _test-output-stream "main:"                   "F - test-convert-function-call-with-literal-arg/0")
 2203     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-literal-arg/1")
 2204     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-literal-arg/2")
 2205     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-literal-arg/3")
 2206     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-literal-arg/4")
 2207     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:loop:"  "F - test-convert-function-call-with-literal-arg/5")
 2208     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-call-with-literal-arg/6")
 2209     (check-next-stream-line-equal _test-output-stream "    (do-add 3 4)"        "F - test-convert-function-call-with-literal-arg/7")
 2210     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/8")
 2211     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-function-with-local-var-in-reg/9")
 2212     (check-next-stream-line-equal _test-output-stream "    e9/jump $main:0x00000001:break/disp32"  "F - test-convert-function-call-with-literal-arg/10")
 2213     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-literal-arg/11")
 2214     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:break:" "F - test-convert-function-call-with-literal-arg/12")
 2215     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-literal-arg/13")
 2216     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-literal-arg/14")
 2217     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-literal-arg/15")
 2218     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-literal-arg/16")
 2219     (check-next-stream-line-equal _test-output-stream "do-add:"                 "F - test-convert-function-call-with-literal-arg/17")
 2220     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-literal-arg/18")
 2221     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-literal-arg/19")
 2222     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-literal-arg/20")
 2223     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-literal-arg/21")
 2224     (check-next-stream-line-equal _test-output-stream "$do-add:0x00000002:loop:"  "F - test-convert-function-call-with-literal-arg/22")
 2225     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-call-with-literal-arg/23")
 2226     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-function-call-with-literal-arg/24")
 2227     (check-next-stream-line-equal _test-output-stream "    03/add *(ebp+0x0000000c) 0x00000000/r32"  "F - test-convert-function-call-with-literal-arg/25")
 2228     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32" "F - test-convert-function-call-with-literal-arg/26")
 2229     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-call-with-literal-arg/27")
 2230     (check-next-stream-line-equal _test-output-stream "    e9/jump $do-add:0x00000002:break/disp32"  "F - test-convert-function-call-with-literal-arg/28")
 2231     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-literal-arg/29")
 2232     (check-next-stream-line-equal _test-output-stream "$do-add:0x00000002:break:"  "F - test-convert-function-call-with-literal-arg/30")
 2233     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-literal-arg/31")
 2234     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-literal-arg/32")
 2235     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-literal-arg/33")
 2236     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-literal-arg/34")
 2237     # . epilogue
 2238     89/<- %esp 5/r32/ebp
 2239     5d/pop-to-ebp
 2240     c3/return
 2241 
 2242 test-convert-function-call-with-literal-string-arg:
 2243     # . prologue
 2244     55/push-ebp
 2245     89/<- %ebp 4/r32/esp
 2246     # setup
 2247     (clear-stream _test-input-stream)
 2248     (clear-stream $_test-input-buffered-file->buffer)
 2249     (clear-stream _test-output-stream)
 2250     (clear-stream $_test-output-buffered-file->buffer)
 2251     #
 2252     (write _test-input-stream "fn foo {\n")
 2253     (write _test-input-stream "  string-func \"abc\"\n")
 2254     (write _test-input-stream "}\n")
 2255     (write _test-input-stream "sig string-func in: (addr array byte)\n")
 2256     # convert
 2257     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2258     # no errors
 2259     # not bothering checking output
 2260     # . epilogue
 2261     89/<- %esp 5/r32/ebp
 2262     5d/pop-to-ebp
 2263     c3/return
 2264 
 2265 test-convert-function-call-with-null-addr:
 2266     # . prologue
 2267     55/push-ebp
 2268     89/<- %ebp 4/r32/esp
 2269     # setup
 2270     (clear-stream _test-input-stream)
 2271     (clear-stream $_test-input-buffered-file->buffer)
 2272     (clear-stream _test-output-stream)
 2273     (clear-stream $_test-output-buffered-file->buffer)
 2274     #
 2275     (write _test-input-stream "fn foo {\n")
 2276     (write _test-input-stream "  bar 0\n")
 2277     (write _test-input-stream "}\n")
 2278     (write _test-input-stream "sig bar in: (addr int)\n")
 2279     # convert
 2280     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2281     # no errors
 2282     # not bothering checking output
 2283     # . epilogue
 2284     89/<- %esp 5/r32/ebp
 2285     5d/pop-to-ebp
 2286     c3/return
 2287 
 2288 test-convert-function-call-with-signature:
 2289     # . prologue
 2290     55/push-ebp
 2291     89/<- %ebp 4/r32/esp
 2292     # setup
 2293     (clear-stream _test-input-stream)
 2294     (clear-stream $_test-input-buffered-file->buffer)
 2295     (clear-stream _test-output-stream)
 2296     (clear-stream $_test-output-buffered-file->buffer)
 2297     #
 2298     (write _test-input-stream "fn main -> _/ebx: int {\n")
 2299     (write _test-input-stream "  var result/eax: int <- do-add 3 4\n")
 2300     (write _test-input-stream "  return result\n")
 2301     (write _test-input-stream "}\n")
 2302     (write _test-input-stream "sig do-add a: int, b: int -> _/eax: int\n")
 2303     # convert
 2304     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2305     (flush _test-output-buffered-file)
 2306 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2312     # check output
 2313     (check-next-stream-line-equal _test-output-stream "main:"                   "F - test-convert-function-call-with-signature/0")
 2314     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-signature/1")
 2315     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-signature/2")
 2316     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-signature/3")
 2317     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-signature/4")
 2318     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:loop:"  "F - test-convert-function-call-with-signature/5")
 2319     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-call-with-literal-arg/6")
 2320     (check-next-stream-line-equal _test-output-stream "    (do-add 3 4)"        "F - test-convert-function-call-with-signature/6")
 2321     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/8")
 2322     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-function-with-local-var-in-reg/9")
 2323     (check-next-stream-line-equal _test-output-stream "    e9/jump $main:0x00000001:break/disp32"  "F - test-convert-function-call-with-literal-arg/10")
 2324     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-signature/7")
 2325     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:break:" "F - test-convert-function-call-with-signature/8")
 2326     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-signature/9")
 2327     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-signature/10")
 2328     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-signature/11")
 2329     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-signature/12")
 2330     # . epilogue
 2331     89/<- %esp 5/r32/ebp
 2332     5d/pop-to-ebp
 2333     c3/return
 2334 
 2335 test-convert-function-with-local-var-in-mem:
 2336     # . prologue
 2337     55/push-ebp
 2338     89/<- %ebp 4/r32/esp
 2339     # setup
 2340     (clear-stream _test-input-stream)
 2341     (clear-stream $_test-input-buffered-file->buffer)
 2342     (clear-stream _test-output-stream)
 2343     (clear-stream $_test-output-buffered-file->buffer)
 2344     #
 2345     (write _test-input-stream "fn foo {\n")
 2346     (write _test-input-stream "  var x: int\n")
 2347     (write _test-input-stream "  increment x\n")
 2348     (write _test-input-stream "}\n")
 2349     # convert
 2350     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2351     (flush _test-output-buffered-file)
 2352 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2358     # check output
 2359     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-mem/0")
 2360     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-mem/1")
 2361     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-mem/2")
 2362     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-mem/3")
 2363     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-mem/4")
 2364     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-mem/5")
 2365     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-in-mem/6")
 2366     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-local-var-in-mem/7")
 2367     (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")
 2368     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-mem/9")
 2369     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-mem/10")
 2370     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-mem/11")
 2371     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-mem/12")
 2372     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-mem/13")
 2373     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-mem/14")
 2374     # . epilogue
 2375     89/<- %esp 5/r32/ebp
 2376     5d/pop-to-ebp
 2377     c3/return
 2378 
 2379 test-convert-invalid-literal:
 2380     # . prologue
 2381     55/push-ebp
 2382     89/<- %ebp 4/r32/esp
 2383     # setup
 2384     (clear-stream _test-input-stream)
 2385     (clear-stream $_test-input-buffered-file->buffer)
 2386     (clear-stream _test-output-stream)
 2387     (clear-stream $_test-output-buffered-file->buffer)
 2388     (clear-stream _test-error-stream)
 2389     (clear-stream $_test-error-buffered-file->buffer)
 2390     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2391     68/push 0/imm32
 2392     68/push 0/imm32
 2393     89/<- %edx 4/r32/esp
 2394     (tailor-exit-descriptor %edx 0x10)
 2395     #
 2396     (write _test-input-stream "fn foo {\n")
 2397     (write _test-input-stream "  increment 1n\n")
 2398     (write _test-input-stream "}\n")
 2399     # convert
 2400     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2401     # registers except esp clobbered at this point
 2402     # restore ed
 2403     89/<- %edx 4/r32/esp
 2404     (flush _test-output-buffered-file)
 2405     (flush _test-error-buffered-file)
 2406 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2412     # check output
 2413     (check-stream-equal _test-output-stream  ""  "F - test-convert-invalid-literal: output should be empty")
 2414     (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")
 2415     # check that stop(1) was called
 2416     (check-ints-equal *(edx+4) 2 "F - test-convert-invalid-literal: exit status")
 2417     # don't restore from ebp
 2418     81 0/subop/add %esp 8/imm32
 2419     # . epilogue
 2420     5d/pop-to-ebp
 2421     c3/return
 2422 
 2423 test-local-var-in-mem-has-no-initializer:
 2424     # . prologue
 2425     55/push-ebp
 2426     89/<- %ebp 4/r32/esp
 2427     # setup
 2428     (clear-stream _test-input-stream)
 2429     (clear-stream $_test-input-buffered-file->buffer)
 2430     (clear-stream _test-output-stream)
 2431     (clear-stream $_test-output-buffered-file->buffer)
 2432     (clear-stream _test-error-stream)
 2433     (clear-stream $_test-error-buffered-file->buffer)
 2434     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2435     68/push 0/imm32
 2436     68/push 0/imm32
 2437     89/<- %edx 4/r32/esp
 2438     (tailor-exit-descriptor %edx 0x10)
 2439     #
 2440     (write _test-input-stream "fn foo {\n")
 2441     (write _test-input-stream "  var x: int <- copy 0\n")
 2442     (write _test-input-stream "  increment x\n")
 2443     (write _test-input-stream "}\n")
 2444     # convert
 2445     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2446     # registers except esp clobbered at this point
 2447     # restore ed
 2448     89/<- %edx 4/r32/esp
 2449     (flush _test-output-buffered-file)
 2450     (flush _test-error-buffered-file)
 2451 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2457     # check output
 2458     (check-stream-equal _test-output-stream  ""  "F - test-var-in-mem-has-no-initializer: output should be empty")
 2459     (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")
 2460     # check that stop(1) was called
 2461     (check-ints-equal *(edx+4) 2 "F - test-var-in-mem-has-no-initializer: exit status")
 2462     # don't restore from ebp
 2463     81 0/subop/add %esp 8/imm32
 2464     # . epilogue
 2465     5d/pop-to-ebp
 2466     c3/return
 2467 
 2468 test-convert-function-with-local-var-with-compound-type-in-mem:
 2469     # . prologue
 2470     55/push-ebp
 2471     89/<- %ebp 4/r32/esp
 2472     # setup
 2473     (clear-stream _test-input-stream)
 2474     (clear-stream $_test-input-buffered-file->buffer)
 2475     (clear-stream _test-output-stream)
 2476     (clear-stream $_test-output-buffered-file->buffer)
 2477     #
 2478     (write _test-input-stream "fn foo {\n")
 2479     (write _test-input-stream "  var x: (addr int)\n")
 2480     (write _test-input-stream "  copy-to x, 0\n")
 2481     (write _test-input-stream "}\n")
 2482     # convert
 2483     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2484     (flush _test-output-buffered-file)
 2485 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2491     # check output
 2492     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-with-compound-type-in-mem/0")
 2493     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-with-compound-type-in-mem/1")
 2494     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-with-compound-type-in-mem/2")
 2495     (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")
 2496     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-with-compound-type-in-mem/4")
 2497     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-with-compound-type-in-mem/5")
 2498     (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")
 2499     (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")
 2500     (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")
 2501     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-with-compound-type-in-mem/9")
 2502     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-with-compound-type-in-mem/10")
 2503     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-with-compound-type-in-mem/11")
 2504     (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")
 2505     (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")
 2506     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-with-compound-type-in-mem/14")
 2507     # . epilogue
 2508     89/<- %esp 5/r32/ebp
 2509     5d/pop-to-ebp
 2510     c3/return
 2511 
 2512 test-convert-function-with-local-var-in-reg:
 2513     # . prologue
 2514     55/push-ebp
 2515     89/<- %ebp 4/r32/esp
 2516     # setup
 2517     (clear-stream _test-input-stream)
 2518     (clear-stream $_test-input-buffered-file->buffer)
 2519     (clear-stream _test-output-stream)
 2520     (clear-stream $_test-output-buffered-file->buffer)
 2521     #
 2522     (write _test-input-stream "fn foo {\n")
 2523     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 2524     (write _test-input-stream "  x <- increment\n")
 2525     (write _test-input-stream "}\n")
 2526     # convert
 2527     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2528     (flush _test-output-buffered-file)
 2529 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2535     # check output
 2536     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-reg/0")
 2537     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-reg/1")
 2538     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-reg/2")
 2539     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-reg/3")
 2540     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-reg/4")
 2541     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-reg/5")
 2542     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-local-var-in-reg/6")
 2543     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-convert-function-with-local-var-in-reg/7")
 2544     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-convert-function-with-local-var-in-reg/8")
 2545     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-local-var-in-reg/9")
 2546     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-reg/10")
 2547     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-reg/11")
 2548     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-reg/12")
 2549     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-reg/13")
 2550     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-reg/14")
 2551     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-reg/15")
 2552     # . epilogue
 2553     89/<- %esp 5/r32/ebp
 2554     5d/pop-to-ebp
 2555     c3/return
 2556 
 2557 test-float-var-in-wrong-register:
 2558     # . prologue
 2559     55/push-ebp
 2560     89/<- %ebp 4/r32/esp
 2561     # setup
 2562     (clear-stream _test-input-stream)
 2563     (clear-stream $_test-input-buffered-file->buffer)
 2564     (clear-stream _test-output-stream)
 2565     (clear-stream $_test-output-buffered-file->buffer)
 2566     (clear-stream _test-error-stream)
 2567     (clear-stream $_test-error-buffered-file->buffer)
 2568     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2569     68/push 0/imm32
 2570     68/push 0/imm32
 2571     89/<- %edx 4/r32/esp
 2572     (tailor-exit-descriptor %edx 0x10)
 2573     #
 2574     (write _test-input-stream "fn foo {\n")
 2575     (write _test-input-stream "  var x/eax: int <- copy 0\n")
 2576     (write _test-input-stream "  var y/eax: float <- convert x\n")
 2577     (write _test-input-stream "}\n")
 2578     # convert
 2579     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2580     # registers except esp clobbered at this point
 2581     # restore ed
 2582     89/<- %edx 4/r32/esp
 2583     (flush _test-output-buffered-file)
 2584     (flush _test-error-buffered-file)
 2585 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2591     # check output
 2592     (check-stream-equal _test-output-stream  ""  "F - test-float-var-in-wrong-register: output should be empty")
 2593     (check-next-stream-line-equal _test-error-stream  "fn foo: float var 'y' should be in a floating-point register"  "F - test-float-var-in-wrong-register: error message")
 2594     # check that stop(1) was called
 2595     (check-ints-equal *(edx+4) 2 "F - test-float-var-in-wrong-register: exit status")
 2596     # don't restore from ebp
 2597     81 0/subop/add %esp 8/imm32
 2598     # . epilogue
 2599     5d/pop-to-ebp
 2600     c3/return
 2601 
 2602 test-non-float-var-in-wrong-register:
 2603     # . prologue
 2604     55/push-ebp
 2605     89/<- %ebp 4/r32/esp
 2606     # setup
 2607     (clear-stream _test-input-stream)
 2608     (clear-stream $_test-input-buffered-file->buffer)
 2609     (clear-stream _test-output-stream)
 2610     (clear-stream $_test-output-buffered-file->buffer)
 2611     (clear-stream _test-error-stream)
 2612     (clear-stream $_test-error-buffered-file->buffer)
 2613     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2614     68/push 0/imm32
 2615     68/push 0/imm32
 2616     89/<- %edx 4/r32/esp
 2617     (tailor-exit-descriptor %edx 0x10)
 2618     #
 2619     (write _test-input-stream "fn foo {\n")
 2620     (write _test-input-stream "  var x/xmm5: int <- copy 0\n")
 2621     (write _test-input-stream "}\n")
 2622     # convert
 2623     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2624     # registers except esp clobbered at this point
 2625     # restore ed
 2626     89/<- %edx 4/r32/esp
 2627     (flush _test-output-buffered-file)
 2628     (flush _test-error-buffered-file)
 2629 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2635     # check output
 2636     (check-stream-equal _test-output-stream  ""  "F - test-non-float-var-in-wrong-register: output should be empty")
 2637     (check-next-stream-line-equal _test-error-stream  "fn foo: non-float var 'x' should be in an integer register"  "F - test-non-float-var-in-wrong-register: error message")
 2638     # check that stop(1) was called
 2639     (check-ints-equal *(edx+4) 2 "F - test-non-float-var-in-wrong-register: exit status")
 2640     # don't restore from ebp
 2641     81 0/subop/add %esp 8/imm32
 2642     # . epilogue
 2643     5d/pop-to-ebp
 2644     c3/return
 2645 
 2646 test-convert-function-with-allocate:
 2647     # . prologue
 2648     55/push-ebp
 2649     89/<- %ebp 4/r32/esp
 2650     # setup
 2651     (clear-stream _test-input-stream)
 2652     (clear-stream $_test-input-buffered-file->buffer)
 2653     (clear-stream _test-output-stream)
 2654     (clear-stream $_test-output-buffered-file->buffer)
 2655     #
 2656     (write _test-input-stream "fn foo {\n")
 2657     (write _test-input-stream "  var x/ecx: (addr handle int) <- copy 0\n")
 2658     (write _test-input-stream "  allocate x\n")
 2659     (write _test-input-stream "}\n")
 2660     # convert
 2661     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2662     (flush _test-output-buffered-file)
 2663 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2669     # check output
 2670     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-allocate/0")
 2671     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-allocate/1")
 2672     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-allocate/2")
 2673     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-allocate/3")
 2674     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-allocate/4")
 2675     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-allocate/5")
 2676     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-allocate/6")
 2677     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-function-with-allocate/7")
 2678     (check-next-stream-line-equal _test-output-stream "    (allocate Heap 0x00000004 %ecx)"  "F - test-convert-function-with-allocate/8")  # 4 = size-of(int)
 2679     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-allocate/9")
 2680     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-allocate/10")
 2681     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-allocate/11")
 2682     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-allocate/12")
 2683     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-allocate/13")
 2684     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-allocate/14")
 2685     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-allocate/15")
 2686     # . epilogue
 2687     89/<- %esp 5/r32/ebp
 2688     5d/pop-to-ebp
 2689     c3/return
 2690 
 2691 test-initializer-in-hex:
 2692     # . prologue
 2693     55/push-ebp
 2694     89/<- %ebp 4/r32/esp
 2695     # setup
 2696     (clear-stream _test-input-stream)
 2697     (clear-stream $_test-input-buffered-file->buffer)
 2698     (clear-stream _test-output-stream)
 2699     (clear-stream $_test-output-buffered-file->buffer)
 2700     (clear-stream _test-error-stream)
 2701     (clear-stream $_test-error-buffered-file->buffer)
 2702     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2703     68/push 0/imm32
 2704     68/push 0/imm32
 2705     89/<- %edx 4/r32/esp
 2706     (tailor-exit-descriptor %edx 0x10)
 2707     #
 2708     (write _test-input-stream "fn foo {\n")
 2709     (write _test-input-stream "  var x/ecx: int <- copy 10\n")
 2710     (write _test-input-stream "}\n")
 2711     # convert
 2712     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2713     # registers except esp clobbered at this point
 2714     # restore ed
 2715     89/<- %edx 4/r32/esp
 2716     (flush _test-output-buffered-file)
 2717     (flush _test-error-buffered-file)
 2718 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2724     # check output
 2725     (check-stream-equal _test-output-stream  ""  "F - test-initializer-in-hex: output should be empty")
 2726     (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")
 2727     # check that stop(1) was called
 2728     (check-ints-equal *(edx+4) 2 "F - test-initializer-in-hex: exit status")
 2729     # don't restore from ebp
 2730     81 0/subop/add %esp 8/imm32
 2731     # . epilogue
 2732     5d/pop-to-ebp
 2733     c3/return
 2734 
 2735 test-convert-function-with-second-local-var-in-same-reg:
 2736     # . prologue
 2737     55/push-ebp
 2738     89/<- %ebp 4/r32/esp
 2739     # setup
 2740     (clear-stream _test-input-stream)
 2741     (clear-stream $_test-input-buffered-file->buffer)
 2742     (clear-stream _test-output-stream)
 2743     (clear-stream $_test-output-buffered-file->buffer)
 2744     #
 2745     (write _test-input-stream "fn foo {\n")
 2746     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 2747     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
 2748     (write _test-input-stream "  y <- increment\n")
 2749     (write _test-input-stream "}\n")
 2750     # convert
 2751     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2752     (flush _test-output-buffered-file)
 2753 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2759     # check output
 2760     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-second-local-var-in-same-reg/0")
 2761     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-second-local-var-in-same-reg/1")
 2762     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-second-local-var-in-same-reg/2")
 2763     (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")
 2764     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-second-local-var-in-same-reg/4")
 2765     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-second-local-var-in-same-reg/5")
 2766     (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")
 2767     (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")
 2768     (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")
 2769     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-convert-function-with-second-local-var-in-same-reg/9")
 2770     (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")
 2771     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-second-local-var-in-same-reg/11")
 2772     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-second-local-var-in-same-reg/12")
 2773     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-second-local-var-in-same-reg/13")
 2774     (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")
 2775     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-second-local-var-in-same-reg/15")
 2776     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-second-local-var-in-same-reg/16")
 2777     # . epilogue
 2778     89/<- %esp 5/r32/ebp
 2779     5d/pop-to-ebp
 2780     c3/return
 2781 
 2782 test-read-clobbered-reg-var:
 2783     # . prologue
 2784     55/push-ebp
 2785     89/<- %ebp 4/r32/esp
 2786     # setup
 2787     (clear-stream _test-input-stream)
 2788     (clear-stream $_test-input-buffered-file->buffer)
 2789     (clear-stream _test-output-stream)
 2790     (clear-stream $_test-output-buffered-file->buffer)
 2791     (clear-stream _test-error-stream)
 2792     (clear-stream $_test-error-buffered-file->buffer)
 2793     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)  # bytes of args in call to convert-mu
 2794     68/push 0/imm32
 2795     68/push 0/imm32
 2796     89/<- %edx 4/r32/esp
 2797     (tailor-exit-descriptor %edx 0x10)
 2798     #
 2799     (write _test-input-stream "fn foo {\n")
 2800     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 2801     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
 2802     (write _test-input-stream "  x <- increment\n")
 2803     (write _test-input-stream "}\n")
 2804     # convert
 2805     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2806     # registers except esp clobbered at this point
 2807     # restore ed
 2808     89/<- %edx 4/r32/esp
 2809     (flush _test-output-buffered-file)
 2810     (flush _test-error-buffered-file)
 2811 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2817     # check output
 2818     (check-stream-equal _test-output-stream  ""  "F - test-read-clobbered-reg-var: output should be empty")
 2819     (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")
 2820     # check that stop(1) was called
 2821     (check-ints-equal *(edx+4) 2 "F - test-read-clobbered-reg-var: exit status")
 2822     # don't restore from ebp
 2823     81 0/subop/add %esp 8/imm32
 2824     # . epilogue
 2825     5d/pop-to-ebp
 2826     c3/return
 2827 
 2828 test-overlapping-int-fp-registers:
 2829     # . prologue
 2830     55/push-ebp
 2831     89/<- %ebp 4/r32/esp
 2832     # setup
 2833     (clear-stream _test-input-stream)
 2834     (clear-stream $_test-input-buffered-file->buffer)
 2835     (clear-stream _test-output-stream)
 2836     (clear-stream $_test-output-buffered-file->buffer)
 2837     (clear-stream _test-error-stream)
 2838     (clear-stream $_test-error-buffered-file->buffer)
 2839     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)  # bytes of args in call to convert-mu
 2840     68/push 0/imm32
 2841     68/push 0/imm32
 2842     89/<- %edx 4/r32/esp
 2843     (tailor-exit-descriptor %edx 0x10)
 2844     #
 2845     (write _test-input-stream "fn foo {\n")
 2846     (write _test-input-stream "  var x/eax: int <- copy 3\n")
 2847     (write _test-input-stream "  var y/xmm0: float <- convert x\n")
 2848     (write _test-input-stream "  x <- increment\n")
 2849     (write _test-input-stream "}\n")
 2850     # convert
 2851     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2852     # registers except esp clobbered at this point
 2853     # restore ed
 2854     89/<- %edx 4/r32/esp
 2855     (flush _test-output-buffered-file)
 2856     (flush _test-error-buffered-file)
 2857 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2863     # no errors
 2864     (check-next-stream-line-equal _test-error-stream  ""  "F - test-overlapping-int-fp-registers: error message")
 2865     # don't bother checking the generated code
 2866     # don't restore from ebp
 2867     81 0/subop/add %esp 8/imm32
 2868     # . epilogue
 2869     5d/pop-to-ebp
 2870     c3/return
 2871 
 2872 test-convert-function-call:
 2873     # . prologue
 2874     55/push-ebp
 2875     89/<- %ebp 4/r32/esp
 2876     # setup
 2877     (clear-stream _test-input-stream)
 2878     (clear-stream $_test-input-buffered-file->buffer)
 2879     (clear-stream _test-output-stream)
 2880     (clear-stream $_test-output-buffered-file->buffer)
 2881     #
 2882     (write _test-input-stream "fn main -> _/ebx: int {\n")
 2883     (write _test-input-stream "  var result/ebx: int <- foo\n")
 2884     (write _test-input-stream "  return result\n")
 2885     (write _test-input-stream "}\n")
 2886     (write _test-input-stream "fn foo -> _/ebx: int {\n")
 2887     (write _test-input-stream "  var result/ebx: int <- copy 3\n")
 2888     (write _test-input-stream "  return result\n")
 2889     (write _test-input-stream "}\n")
 2890     # convert
 2891     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2892     (flush _test-output-buffered-file)
 2893 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2899     # check output
 2900     (check-next-stream-line-equal _test-output-stream "main:"                   "F - test-convert-function-call/0")
 2901     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call/1")
 2902     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call/2")
 2903     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call/3")
 2904     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call/4")
 2905     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:loop:"  "F - test-convert-function-call/5")
 2906     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ebx"  "F - test-convert-function-call-with-literal-arg/6")
 2907     (check-next-stream-line-equal _test-output-stream "    (foo)"               "F - test-convert-function-call/6")
 2908     (check-next-stream-line-equal _test-output-stream "    8b/-> %ebx 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/8")
 2909     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-call-with-literal-arg/27")
 2910     (check-next-stream-line-equal _test-output-stream "    e9/jump $main:0x00000001:break/disp32"  "F - test-convert-function-call-with-literal-arg/10")
 2911     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call/7")
 2912     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:break:" "F - test-convert-function-call/8")
 2913     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call/9")
 2914     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call/10")
 2915     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call/11")
 2916     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call/12")
 2917     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call/13")
 2918     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call/14")
 2919     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call/15")
 2920     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call/16")
 2921     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call/17")
 2922     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"  "F - test-convert-function-call/18")
 2923     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ebx"  "F - test-convert-function-call-with-literal-arg/6")
 2924     (check-next-stream-line-equal _test-output-stream "    bb/copy-to-ebx 3/imm32"  "F - test-convert-function-call/19")
 2925     (check-next-stream-line-equal _test-output-stream "    8b/-> %ebx 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/8")
 2926     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-call-with-literal-arg/27")
 2927     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-call-with-literal-arg/10")
 2928     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call/20")
 2929     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-call/21")
 2930     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call/22")
 2931     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call/23")
 2932     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call/24")
 2933     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call/25")
 2934     # . epilogue
 2935     89/<- %esp 5/r32/ebp
 2936     5d/pop-to-ebp
 2937     c3/return
 2938 
 2939 test-convert-function-call-with-inout-with-compound-type:
 2940     # . prologue
 2941     55/push-ebp
 2942     89/<- %ebp 4/r32/esp
 2943     # setup
 2944     (clear-stream _test-input-stream)
 2945     (clear-stream $_test-input-buffered-file->buffer)
 2946     (clear-stream _test-output-stream)
 2947     (clear-stream $_test-output-buffered-file->buffer)
 2948     #
 2949     (write _test-input-stream "fn f {\n")
 2950     (write _test-input-stream "  var x: (addr int)\n")
 2951     (write _test-input-stream "  g x\n")
 2952     (write _test-input-stream "}\n")
 2953     (write _test-input-stream "fn g a: (addr int) {\n")
 2954     (write _test-input-stream "}\n")
 2955     # convert
 2956     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2957     (flush _test-output-buffered-file)
 2958 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2964     # check output
 2965     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-inout-with-compound-type/0")
 2966     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-inout-with-compound-type/1")
 2967     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-inout-with-compound-type/2")
 2968     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-inout-with-compound-type/3")
 2969     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-inout-with-compound-type/4")
 2970     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"     "F - test-convert-function-call-with-inout-with-compound-type/5")
 2971     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-call-with-inout-with-compound-type/6")
 2972     (check-next-stream-line-equal _test-output-stream "    (g *(ebp+0xfffffffc))"  "F - test-convert-function-call-with-inout-with-compound-type/7")
 2973     (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")
 2974     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-inout-with-compound-type/9")
 2975     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"    "F - test-convert-function-call-with-inout-with-compound-type/10")
 2976     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-inout-with-compound-type/11")
 2977     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-inout-with-compound-type/12")
 2978     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-inout-with-compound-type/13")
 2979     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-inout-with-compound-type/14")
 2980     (check-next-stream-line-equal _test-output-stream "g:"                      "F - test-convert-function-call-with-inout-with-compound-type/15")
 2981     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-inout-with-compound-type/16")
 2982     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-inout-with-compound-type/17")
 2983     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-inout-with-compound-type/18")
 2984     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-inout-with-compound-type/19")
 2985     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-inout-with-compound-type/20")
 2986     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-inout-with-compound-type/21")
 2987     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-inout-with-compound-type/22")
 2988     # . epilogue
 2989     89/<- %esp 5/r32/ebp
 2990     5d/pop-to-ebp
 2991     c3/return
 2992 
 2993 test-convert-function-call-with-inout-with-type-parameter:
 2994     # . prologue
 2995     55/push-ebp
 2996     89/<- %ebp 4/r32/esp
 2997     # setup
 2998     (clear-stream _test-input-stream)
 2999     (clear-stream $_test-input-buffered-file->buffer)
 3000     (clear-stream _test-output-stream)
 3001     (clear-stream $_test-output-buffered-file->buffer)
 3002     (clear-stream _test-error-stream)
 3003     (clear-stream $_test-error-buffered-file->buffer)
 3004     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3005     68/push 0/imm32
 3006     68/push 0/imm32
 3007     89/<- %edx 4/r32/esp
 3008     (tailor-exit-descriptor %edx 0x10)
 3009     #
 3010     (write _test-input-stream "fn f {\n")
 3011     (write _test-input-stream "  var x: (addr int)\n")
 3012     (write _test-input-stream "  g x\n")
 3013     (write _test-input-stream "}\n")
 3014     (write _test-input-stream "fn g a: (addr _) {\n")
 3015     (write _test-input-stream "}\n")
 3016     # convert
 3017     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3018     # registers except esp clobbered at this point
 3019     # restore ed
 3020     89/<- %edx 4/r32/esp
 3021     (flush _test-output-buffered-file)
 3022     (flush _test-error-buffered-file)
 3023 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3029     # no error; types matched
 3030     (check-stream-equal _test-error-stream  ""  "F - test-convert-function-call-with-inout-with-type-parameter: error stream should be empty")
 3031     # don't bother checking the generated code; that's in the test 'test-local-clobbered-by-fn-output' below
 3032     # don't restore from ebp
 3033     81 0/subop/add %esp 8/imm32
 3034     # . epilogue
 3035     5d/pop-to-ebp
 3036     c3/return
 3037 
 3038 test-convert-function-call-with-incorrect-inout-type:
 3039     # . prologue
 3040     55/push-ebp
 3041     89/<- %ebp 4/r32/esp
 3042     # setup
 3043     (clear-stream _test-input-stream)
 3044     (clear-stream $_test-input-buffered-file->buffer)
 3045     (clear-stream _test-output-stream)
 3046     (clear-stream $_test-output-buffered-file->buffer)
 3047     (clear-stream _test-error-stream)
 3048     (clear-stream $_test-error-buffered-file->buffer)
 3049     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3050     68/push 0/imm32
 3051     68/push 0/imm32
 3052     89/<- %edx 4/r32/esp
 3053     (tailor-exit-descriptor %edx 0x10)
 3054     #
 3055     (write _test-input-stream "fn f {\n")
 3056     (write _test-input-stream "  var x: int\n")
 3057     (write _test-input-stream "  g x\n")
 3058     (write _test-input-stream "}\n")
 3059     (write _test-input-stream "fn g a: foo {\n")
 3060     (write _test-input-stream "}\n")
 3061     # convert
 3062     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3063     # registers except esp clobbered at this point
 3064     # restore ed
 3065     89/<- %edx 4/r32/esp
 3066     (flush _test-output-buffered-file)
 3067     (flush _test-error-buffered-file)
 3068 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3074     # check output
 3075     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-incorrect-inout-type: output should be empty")
 3076     (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")
 3077     # check that stop(1) was called
 3078     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-incorrect-inout-type: exit status")
 3079     # don't restore from ebp
 3080     81 0/subop/add %esp 8/imm32
 3081     5d/pop-to-ebp
 3082     c3/return
 3083 
 3084 test-convert-function-call-with-inout-with-incorrect-compound-type:
 3085     # . prologue
 3086     55/push-ebp
 3087     89/<- %ebp 4/r32/esp
 3088     # setup
 3089     (clear-stream _test-input-stream)
 3090     (clear-stream $_test-input-buffered-file->buffer)
 3091     (clear-stream _test-output-stream)
 3092     (clear-stream $_test-output-buffered-file->buffer)
 3093     (clear-stream _test-error-stream)
 3094     (clear-stream $_test-error-buffered-file->buffer)
 3095     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3096     68/push 0/imm32
 3097     68/push 0/imm32
 3098     89/<- %edx 4/r32/esp
 3099     (tailor-exit-descriptor %edx 0x10)
 3100     #
 3101     (write _test-input-stream "fn f {\n")
 3102     (write _test-input-stream "  var x: (addr int)\n")
 3103     (write _test-input-stream "  g x\n")
 3104     (write _test-input-stream "}\n")
 3105     (write _test-input-stream "fn g a: (addr bool) {\n")
 3106     (write _test-input-stream "}\n")
 3107     # convert
 3108     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3109     # registers except esp clobbered at this point
 3110     # restore ed
 3111     89/<- %edx 4/r32/esp
 3112     (flush _test-output-buffered-file)
 3113     (flush _test-error-buffered-file)
 3114 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3120     # check output
 3121     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-inout-with-incorrect-compound-type: output should be empty")
 3122     (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")
 3123     # don't restore from ebp
 3124     81 0/subop/add %esp 8/imm32
 3125     # . epilogue
 3126     5d/pop-to-ebp
 3127     c3/return
 3128 
 3129 test-convert-function-call-with-inout-with-multiple-type-parameters:
 3130     # . prologue
 3131     55/push-ebp
 3132     89/<- %ebp 4/r32/esp
 3133     # setup
 3134     (clear-stream _test-input-stream)
 3135     (clear-stream $_test-input-buffered-file->buffer)
 3136     (clear-stream _test-output-stream)
 3137     (clear-stream $_test-output-buffered-file->buffer)
 3138     (clear-stream _test-error-stream)
 3139     (clear-stream $_test-error-buffered-file->buffer)
 3140     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3141     68/push 0/imm32
 3142     68/push 0/imm32
 3143     89/<- %edx 4/r32/esp
 3144     (tailor-exit-descriptor %edx 0x10)
 3145     #
 3146     (write _test-input-stream "fn f {\n")
 3147     (write _test-input-stream "  var x: (addr int)\n")
 3148     (write _test-input-stream "  var y: (addr int)\n")
 3149     (write _test-input-stream "  g x, y\n")
 3150     (write _test-input-stream "}\n")
 3151     (write _test-input-stream "fn g a: (addr _), b: (addr _) {\n")
 3152     (write _test-input-stream "}\n")
 3153     # convert
 3154     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3155     # registers except esp clobbered at this point
 3156     # restore ed
 3157     89/<- %edx 4/r32/esp
 3158     (flush _test-output-buffered-file)
 3159     (flush _test-error-buffered-file)
 3160 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3166     # no errors
 3167     (check-stream-equal _test-error-stream  ""  "F - test-convert-function-call-with-inout-with-multiple-type-parameters: error stream should be empty")
 3168     # don't bother checking the generated code
 3169     # don't restore from ebp
 3170     81 0/subop/add %esp 8/imm32
 3171     # . epilogue
 3172     5d/pop-to-ebp
 3173     c3/return
 3174 
 3175 test-type-parameter-matches-rest-of-type:
 3176     # . prologue
 3177     55/push-ebp
 3178     89/<- %ebp 4/r32/esp
 3179     # setup
 3180     (clear-stream _test-input-stream)
 3181     (clear-stream $_test-input-buffered-file->buffer)
 3182     (clear-stream _test-output-stream)
 3183     (clear-stream $_test-output-buffered-file->buffer)
 3184     (clear-stream _test-error-stream)
 3185     (clear-stream $_test-error-buffered-file->buffer)
 3186     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3187     68/push 0/imm32
 3188     68/push 0/imm32
 3189     89/<- %edx 4/r32/esp
 3190     (tailor-exit-descriptor %edx 0x10)
 3191     #
 3192     (write _test-input-stream "fn f {\n")
 3193     (write _test-input-stream "  var x: (addr array int)\n")
 3194     (write _test-input-stream "  g x\n")
 3195     (write _test-input-stream "}\n")
 3196     (write _test-input-stream "fn g a: (addr _) {\n")
 3197     (write _test-input-stream "}\n")
 3198     # convert
 3199     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3200     # registers except esp clobbered at this point
 3201     # restore ed
 3202     89/<- %edx 4/r32/esp
 3203     (flush _test-output-buffered-file)
 3204     (flush _test-error-buffered-file)
 3205 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3211     # no errors
 3212     (check-stream-equal _test-error-stream  ""  "F - test-type-parameter-matches-rest-of-type: error stream should be empty")
 3213     # don't bother checking the generated code
 3214     # don't restore from ebp
 3215     81 0/subop/add %esp 8/imm32
 3216     # . epilogue
 3217     5d/pop-to-ebp
 3218     c3/return
 3219 
 3220 test-convert-function-call-with-inout-with-incompatible-type-parameters:
 3221     # . prologue
 3222     55/push-ebp
 3223     89/<- %ebp 4/r32/esp
 3224     # setup
 3225     (clear-stream _test-input-stream)
 3226     (clear-stream $_test-input-buffered-file->buffer)
 3227     (clear-stream _test-output-stream)
 3228     (clear-stream $_test-output-buffered-file->buffer)
 3229     (clear-stream _test-error-stream)
 3230     (clear-stream $_test-error-buffered-file->buffer)
 3231     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3232     68/push 0/imm32
 3233     68/push 0/imm32
 3234     89/<- %edx 4/r32/esp
 3235     (tailor-exit-descriptor %edx 0x10)
 3236     #
 3237     (write _test-input-stream "fn f {\n")
 3238     (write _test-input-stream "  var x: (addr int)\n")
 3239     (write _test-input-stream "  var y: (addr boolean)\n")
 3240     (write _test-input-stream "  g x, y\n")
 3241     (write _test-input-stream "}\n")
 3242     (write _test-input-stream "fn g a: (addr _T), b: (addr _T) {\n")
 3243     (write _test-input-stream "}\n")
 3244     # convert
 3245     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3246     # registers except esp clobbered at this point
 3247     # restore ed
 3248     89/<- %edx 4/r32/esp
 3249     (flush _test-output-buffered-file)
 3250     (flush _test-error-buffered-file)
 3251 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3257     # check output
 3258     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-inout-with-incompatible-type-parameters: output should be empty")
 3259     (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")
 3260     # don't restore from ebp
 3261     81 0/subop/add %esp 8/imm32
 3262     # . epilogue
 3263     5d/pop-to-ebp
 3264     c3/return
 3265 
 3266 test-convert-function-call-with-too-few-inouts:
 3267     # . prologue
 3268     55/push-ebp
 3269     89/<- %ebp 4/r32/esp
 3270     # setup
 3271     (clear-stream _test-input-stream)
 3272     (clear-stream $_test-input-buffered-file->buffer)
 3273     (clear-stream _test-output-stream)
 3274     (clear-stream $_test-output-buffered-file->buffer)
 3275     (clear-stream _test-error-stream)
 3276     (clear-stream $_test-error-buffered-file->buffer)
 3277     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3278     68/push 0/imm32
 3279     68/push 0/imm32
 3280     89/<- %edx 4/r32/esp
 3281     (tailor-exit-descriptor %edx 0x10)
 3282     #
 3283     (write _test-input-stream "fn f {\n")
 3284     (write _test-input-stream "  g\n")
 3285     (write _test-input-stream "}\n")
 3286     (write _test-input-stream "fn g a: int {\n")
 3287     (write _test-input-stream "}\n")
 3288     # convert
 3289     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3290     # registers except esp clobbered at this point
 3291     # restore ed
 3292     89/<- %edx 4/r32/esp
 3293     (flush _test-output-buffered-file)
 3294     (flush _test-error-buffered-file)
 3295 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3301     # check output
 3302     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-few-inouts: output should be empty")
 3303     (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")
 3304     # check that stop(1) was called
 3305     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-few-inouts: exit status")
 3306     # don't restore from ebp
 3307     81 0/subop/add %esp 8/imm32
 3308     5d/pop-to-ebp
 3309     c3/return
 3310 
 3311 test-convert-function-call-with-too-many-inouts:
 3312     # . prologue
 3313     55/push-ebp
 3314     89/<- %ebp 4/r32/esp
 3315     # setup
 3316     (clear-stream _test-input-stream)
 3317     (clear-stream $_test-input-buffered-file->buffer)
 3318     (clear-stream _test-output-stream)
 3319     (clear-stream $_test-output-buffered-file->buffer)
 3320     (clear-stream _test-error-stream)
 3321     (clear-stream $_test-error-buffered-file->buffer)
 3322     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3323     68/push 0/imm32
 3324     68/push 0/imm32
 3325     89/<- %edx 4/r32/esp
 3326     (tailor-exit-descriptor %edx 0x10)
 3327     #
 3328     (write _test-input-stream "fn f {\n")
 3329     (write _test-input-stream "  var x: int\n")
 3330     (write _test-input-stream "  g x\n")
 3331     (write _test-input-stream "}\n")
 3332     (write _test-input-stream "fn g {\n")
 3333     (write _test-input-stream "}\n")
 3334     # convert
 3335     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3336     # registers except esp clobbered at this point
 3337     # restore ed
 3338     89/<- %edx 4/r32/esp
 3339     (flush _test-output-buffered-file)
 3340     (flush _test-error-buffered-file)
 3341 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3347     # check output
 3348     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-many-inouts: output should be empty")
 3349     (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")
 3350     # check that stop(1) was called
 3351     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-many-inouts: exit status")
 3352     # don't restore from ebp
 3353     81 0/subop/add %esp 8/imm32
 3354     5d/pop-to-ebp
 3355     c3/return
 3356 
 3357 test-convert-function-call-with-incorrect-output-type:
 3358     # . prologue
 3359     55/push-ebp
 3360     89/<- %ebp 4/r32/esp
 3361     # setup
 3362     (clear-stream _test-input-stream)
 3363     (clear-stream $_test-input-buffered-file->buffer)
 3364     (clear-stream _test-output-stream)
 3365     (clear-stream $_test-output-buffered-file->buffer)
 3366     (clear-stream _test-error-stream)
 3367     (clear-stream $_test-error-buffered-file->buffer)
 3368     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3369     68/push 0/imm32
 3370     68/push 0/imm32
 3371     89/<- %edx 4/r32/esp
 3372     (tailor-exit-descriptor %edx 0x10)
 3373     #
 3374     (write _test-input-stream "fn f {\n")
 3375     (write _test-input-stream "  var x/eax: int <- g\n")
 3376     (write _test-input-stream "}\n")
 3377     (write _test-input-stream "fn g -> _/eax: foo {\n")
 3378     (write _test-input-stream "}\n")
 3379     # convert
 3380     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3381     # registers except esp clobbered at this point
 3382     # restore ed
 3383     89/<- %edx 4/r32/esp
 3384     (flush _test-output-buffered-file)
 3385     (flush _test-error-buffered-file)
 3386 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3392     # check output
 3393     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-incorrect-output-type: output should be empty")
 3394     (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")
 3395     # check that stop(1) was called
 3396     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-incorrect-output-type: exit status")
 3397     # don't restore from ebp
 3398     81 0/subop/add %esp 8/imm32
 3399     5d/pop-to-ebp
 3400     c3/return
 3401 
 3402 test-convert-function-call-with-too-few-outputs:
 3403     # . prologue
 3404     55/push-ebp
 3405     89/<- %ebp 4/r32/esp
 3406     # setup
 3407     (clear-stream _test-input-stream)
 3408     (clear-stream $_test-input-buffered-file->buffer)
 3409     (clear-stream _test-output-stream)
 3410     (clear-stream $_test-output-buffered-file->buffer)
 3411     (clear-stream _test-error-stream)
 3412     (clear-stream $_test-error-buffered-file->buffer)
 3413     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3414     68/push 0/imm32
 3415     68/push 0/imm32
 3416     89/<- %edx 4/r32/esp
 3417     (tailor-exit-descriptor %edx 0x10)
 3418     #
 3419     (write _test-input-stream "fn f {\n")
 3420     (write _test-input-stream "  g\n")
 3421     (write _test-input-stream "}\n")
 3422     (write _test-input-stream "fn g -> _/eax: int {\n")
 3423     (write _test-input-stream "}\n")
 3424     # convert
 3425     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3426     # registers except esp clobbered at this point
 3427     # restore ed
 3428     89/<- %edx 4/r32/esp
 3429     (flush _test-output-buffered-file)
 3430     (flush _test-error-buffered-file)
 3431 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3437     # check output
 3438     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-few-outputs: output should be empty")
 3439     (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")
 3440     # check that stop(1) was called
 3441     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-few-outputs: exit status")
 3442     # don't restore from ebp
 3443     81 0/subop/add %esp 8/imm32
 3444     5d/pop-to-ebp
 3445     c3/return
 3446 
 3447 test-convert-function-call-with-too-many-outputs:
 3448     # . prologue
 3449     55/push-ebp
 3450     89/<- %ebp 4/r32/esp
 3451     # setup
 3452     (clear-stream _test-input-stream)
 3453     (clear-stream $_test-input-buffered-file->buffer)
 3454     (clear-stream _test-output-stream)
 3455     (clear-stream $_test-output-buffered-file->buffer)
 3456     (clear-stream _test-error-stream)
 3457     (clear-stream $_test-error-buffered-file->buffer)
 3458     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3459     68/push 0/imm32
 3460     68/push 0/imm32
 3461     89/<- %edx 4/r32/esp
 3462     (tailor-exit-descriptor %edx 0x10)
 3463     #
 3464     (write _test-input-stream "fn f {\n")
 3465     (write _test-input-stream "  var x/eax: int <- g\n")
 3466     (write _test-input-stream "}\n")
 3467     (write _test-input-stream "fn g {\n")
 3468     (write _test-input-stream "}\n")
 3469     # convert
 3470     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3471     # registers except esp clobbered at this point
 3472     # restore ed
 3473     89/<- %edx 4/r32/esp
 3474     (flush _test-output-buffered-file)
 3475     (flush _test-error-buffered-file)
 3476 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3482     # check output
 3483     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-many-outputs: output should be empty")
 3484     (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")
 3485     # check that stop(1) was called
 3486     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-many-outputs: exit status")
 3487     # don't restore from ebp
 3488     81 0/subop/add %esp 8/imm32
 3489     5d/pop-to-ebp
 3490     c3/return
 3491 
 3492 test-convert-function-call-with-missing-output-register:
 3493     # . prologue
 3494     55/push-ebp
 3495     89/<- %ebp 4/r32/esp
 3496     # setup
 3497     (clear-stream _test-input-stream)
 3498     (clear-stream $_test-input-buffered-file->buffer)
 3499     (clear-stream _test-output-stream)
 3500     (clear-stream $_test-output-buffered-file->buffer)
 3501     (clear-stream _test-error-stream)
 3502     (clear-stream $_test-error-buffered-file->buffer)
 3503     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3504     68/push 0/imm32
 3505     68/push 0/imm32
 3506     89/<- %edx 4/r32/esp
 3507     (tailor-exit-descriptor %edx 0x10)
 3508     #
 3509     (write _test-input-stream "fn f {\n")
 3510     (write _test-input-stream "  var x: int\n")
 3511     (write _test-input-stream "  x <- g\n")
 3512     (write _test-input-stream "}\n")
 3513     (write _test-input-stream "fn g -> _/eax: int {\n")
 3514     (write _test-input-stream "}\n")
 3515     # convert
 3516     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3517     # registers except esp clobbered at this point
 3518     # restore ed
 3519     89/<- %edx 4/r32/esp
 3520     (flush _test-output-buffered-file)
 3521     (flush _test-error-buffered-file)
 3522 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3528     # check output
 3529     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-missing-output-register: output should be empty")
 3530     (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")
 3531     # check that stop(1) was called
 3532     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-missing-output-register: exit status")
 3533     # don't restore from ebp
 3534     81 0/subop/add %esp 8/imm32
 3535     5d/pop-to-ebp
 3536     c3/return
 3537 
 3538 test-convert-function-call-with-incorrect-output-register:
 3539     # . prologue
 3540     55/push-ebp
 3541     89/<- %ebp 4/r32/esp
 3542     # setup
 3543     (clear-stream _test-input-stream)
 3544     (clear-stream $_test-input-buffered-file->buffer)
 3545     (clear-stream _test-output-stream)
 3546     (clear-stream $_test-output-buffered-file->buffer)
 3547     (clear-stream _test-error-stream)
 3548     (clear-stream $_test-error-buffered-file->buffer)
 3549     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3550     68/push 0/imm32
 3551     68/push 0/imm32
 3552     89/<- %edx 4/r32/esp
 3553     (tailor-exit-descriptor %edx 0x10)
 3554     #
 3555     (write _test-input-stream "fn f {\n")
 3556     (write _test-input-stream "  var x/ecx: int <- g\n")
 3557     (write _test-input-stream "}\n")
 3558     (write _test-input-stream "fn g -> _/eax: int {\n")
 3559     (write _test-input-stream "}\n")
 3560     # convert
 3561     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3562     # registers except esp clobbered at this point
 3563     # restore ed
 3564     89/<- %edx 4/r32/esp
 3565     (flush _test-output-buffered-file)
 3566     (flush _test-error-buffered-file)
 3567 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3573     # check output
 3574     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-incorrect-output-register: output should be empty")
 3575     (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")
 3576     # check that stop(1) was called
 3577     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-incorrect-output-register: exit status")
 3578     # don't restore from ebp
 3579     81 0/subop/add %esp 8/imm32
 3580     5d/pop-to-ebp
 3581     c3/return
 3582 
 3583 test-convert-function-with-local-var-dereferenced:
 3584     # . prologue
 3585     55/push-ebp
 3586     89/<- %ebp 4/r32/esp
 3587     # setup
 3588     (clear-stream _test-input-stream)
 3589     (clear-stream $_test-input-buffered-file->buffer)
 3590     (clear-stream _test-output-stream)
 3591     (clear-stream $_test-output-buffered-file->buffer)
 3592     #
 3593     (write _test-input-stream "fn foo {\n")
 3594     (write _test-input-stream "  var x/ecx: (addr int) <- copy 0\n")
 3595     (write _test-input-stream "  increment *x\n")
 3596     (write _test-input-stream "}\n")
 3597     # convert
 3598     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3599     (flush _test-output-buffered-file)
 3600 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 3606     # check output
 3607     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-dereferenced/0")
 3608     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-dereferenced/1")
 3609     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-dereferenced/2")
 3610     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-dereferenced/3")
 3611     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-dereferenced/4")
 3612     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-dereferenced/5")
 3613     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-local-var-dereferenced/6")
 3614     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-function-with-local-var-dereferenced/7")
 3615     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *ecx"  "F - test-convert-function-with-local-var-dereferenced/8")
 3616     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-local-var-dereferenced/9")
 3617     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-dereferenced/10")
 3618     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-dereferenced/11")
 3619     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-dereferenced/12")
 3620     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-dereferenced/13")
 3621     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-dereferenced/14")
 3622     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-dereferenced/15")
 3623     # . epilogue
 3624     89/<- %esp 5/r32/ebp
 3625     5d/pop-to-ebp
 3626     c3/return
 3627 
 3628 test-dereference-of-var-on-stack:
 3629     # . prologue
 3630     55/push-ebp
 3631     89/<- %ebp 4/r32/esp
 3632     # setup
 3633     (clear-stream _test-input-stream)
 3634     (clear-stream $_test-input-buffered-file->buffer)
 3635     (clear-stream _test-output-stream)
 3636     (clear-stream $_test-output-buffered-file->buffer)
 3637     (clear-stream _test-error-stream)
 3638     (clear-stream $_test-error-buffered-file->buffer)
 3639     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3640     68/push 0/imm32
 3641     68/push 0/imm32
 3642     89/<- %edx 4/r32/esp
 3643     (tailor-exit-descriptor %edx 0x10)
 3644     #
 3645     (write _test-input-stream "fn foo {\n")
 3646     (write _test-input-stream "  var x: (addr int)\n")
 3647     (write _test-input-stream "  increment *x\n")
 3648     (write _test-input-stream "}\n")
 3649     # convert
 3650     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3651     # registers except esp clobbered at this point
 3652     # restore ed
 3653     89/<- %edx 4/r32/esp
 3654     (flush _test-output-buffered-file)
 3655     (flush _test-error-buffered-file)
 3656 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3662     # check output
 3663     (check-stream-equal _test-output-stream  ""  "F - test-dereference-of-var-on-stack: output should be empty")
 3664     (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")
 3665     # check that stop(1) was called
 3666     (check-ints-equal *(edx+4) 2 "F - test-dereference-of-var-on-stack: exit status")
 3667     # don't restore from ebp
 3668     81 0/subop/add %esp 8/imm32
 3669     # . epilogue
 3670     5d/pop-to-ebp
 3671     c3/return
 3672 
 3673 test-convert-function-with-byte-operations:
 3674     # . prologue
 3675     55/push-ebp
 3676     89/<- %ebp 4/r32/esp
 3677     # setup
 3678     (clear-stream _test-input-stream)
 3679     (clear-stream $_test-input-buffered-file->buffer)
 3680     (clear-stream _test-output-stream)
 3681     (clear-stream $_test-output-buffered-file->buffer)
 3682     #
 3683     (write _test-input-stream "fn foo {\n")
 3684     (write _test-input-stream "  var x/eax: byte <- copy 0\n")
 3685     (write _test-input-stream "  var y/ecx: byte <- copy 0\n")
 3686     (write _test-input-stream "  y <- copy-byte x\n")
 3687     (write _test-input-stream "  var z/edx: (addr byte) <- copy 0\n")
 3688     (write _test-input-stream "  y <- copy-byte *z\n")
 3689     (write _test-input-stream "  copy-byte-to *z, x\n")
 3690     (write _test-input-stream "}\n")
 3691     # convert
 3692     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3693     (flush _test-output-buffered-file)
 3694 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 3700     # check output
 3701     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-function-with-byte-operations/0")
 3702     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-function-with-byte-operations/1")
 3703     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-function-with-byte-operations/2")
 3704     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-function-with-byte-operations/3")
 3705     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-function-with-byte-operations/4")
 3706     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-function-with-byte-operations/5")
 3707     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-function-with-byte-operations/6")
 3708     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-function-with-byte-operations/7")
 3709     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-function-with-byte-operations/8")
 3710     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"                  "F - test-convert-function-with-byte-operations/9")
 3711     (check-next-stream-line-equal _test-output-stream "    8a/byte-> %eax 0x00000001/r32"           "F - test-convert-function-with-byte-operations/10")
 3712     (check-next-stream-line-equal _test-output-stream "    81 4/subop/and %ecx 0xff/imm32"          "F - test-convert-function-with-byte-operations/11")
 3713     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %edx"                    "F - test-convert-function-with-byte-operations/12")
 3714     (check-next-stream-line-equal _test-output-stream "    ba/copy-to-edx 0/imm32"                  "F - test-convert-function-with-byte-operations/13")
 3715     (check-next-stream-line-equal _test-output-stream "    8a/byte-> *edx 0x00000001/r32"           "F - test-convert-function-with-byte-operations/14")
 3716     (check-next-stream-line-equal _test-output-stream "    81 4/subop/and %ecx 0xff/imm32"          "F - test-convert-function-with-byte-operations/15")
 3717     (check-next-stream-line-equal _test-output-stream "    88/byte<- *edx 0x00000000/r32"           "F - test-convert-function-with-byte-operations/16")
 3718     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %edx"                     "F - test-convert-function-with-byte-operations/17")
 3719     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-function-with-byte-operations/18")
 3720     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-function-with-byte-operations/19")
 3721     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-function-with-byte-operations/20")
 3722     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-function-with-byte-operations/21")
 3723     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-function-with-byte-operations/22")
 3724     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-function-with-byte-operations/23")
 3725     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-function-with-byte-operations/24")
 3726     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-function-with-byte-operations/25")
 3727     # . epilogue
 3728     89/<- %esp 5/r32/ebp
 3729     5d/pop-to-ebp
 3730     c3/return
 3731 
 3732 # variables of type 'byte' are not allowed on the stack
 3733 test-byte-values-on-stack:
 3734     # . prologue
 3735     55/push-ebp
 3736     89/<- %ebp 4/r32/esp
 3737     # setup
 3738     (clear-stream _test-input-stream)
 3739     (clear-stream $_test-input-buffered-file->buffer)
 3740     (clear-stream _test-output-stream)
 3741     (clear-stream $_test-output-buffered-file->buffer)
 3742     (clear-stream _test-error-stream)
 3743     (clear-stream $_test-error-buffered-file->buffer)
 3744     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3745     68/push 0/imm32
 3746     68/push 0/imm32
 3747     89/<- %edx 4/r32/esp
 3748     (tailor-exit-descriptor %edx 0x10)
 3749     #
 3750     (write _test-input-stream "fn foo {\n")
 3751     (write _test-input-stream "  var x: byte\n")
 3752     (write _test-input-stream "}\n")
 3753     # convert
 3754     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3755     # registers except esp clobbered at this point
 3756     # restore ed
 3757     89/<- %edx 4/r32/esp
 3758     (flush _test-output-buffered-file)
 3759     (flush _test-error-buffered-file)
 3760 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3766     # check output
 3767     (check-stream-equal _test-output-stream  ""  "F - test-byte-values-on-stack: output should be empty")
 3768     (check-next-stream-line-equal _test-error-stream  "fn foo: var 'x' of type 'byte' cannot be on the stack"  "F - test-byte-values-on-stack: error message")
 3769     # check that stop(1) was called
 3770     (check-ints-equal *(edx+4) 2 "F - test-byte-values-on-stack: exit status")
 3771     # don't restore from ebp
 3772     81 0/subop/add %esp 8/imm32
 3773     # . epilogue
 3774     5d/pop-to-ebp
 3775     c3/return
 3776 
 3777 # variables of type 'byte' are not allowed in esi or edi
 3778 test-byte-values-in-unsupported-registers:
 3779     # . prologue
 3780     55/push-ebp
 3781     89/<- %ebp 4/r32/esp
 3782     # setup
 3783     (clear-stream _test-input-stream)
 3784     (clear-stream $_test-input-buffered-file->buffer)
 3785     (clear-stream _test-output-stream)
 3786     (clear-stream $_test-output-buffered-file->buffer)
 3787     (clear-stream _test-error-stream)
 3788     (clear-stream $_test-error-buffered-file->buffer)
 3789     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3790     68/push 0/imm32
 3791     68/push 0/imm32
 3792     89/<- %edx 4/r32/esp
 3793     (tailor-exit-descriptor %edx 0x10)
 3794     #
 3795     (write _test-input-stream "fn foo {\n")
 3796     (write _test-input-stream "  var x/esi: byte <- copy 0\n")
 3797     (write _test-input-stream "}\n")
 3798     # convert
 3799     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3800     # registers except esp clobbered at this point
 3801     # restore ed
 3802     89/<- %edx 4/r32/esp
 3803     (flush _test-output-buffered-file)
 3804     (flush _test-error-buffered-file)
 3805 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3811     # check output
 3812     (check-stream-equal _test-output-stream  ""  "F - test-byte-values-in-unsupported-registers: output should be empty")
 3813     (check-next-stream-line-equal _test-error-stream  "fn foo: var 'x' of type 'byte' cannot be in esi or edi"  "F - test-byte-values-in-unsupported-registers: error message")
 3814     # check that stop(1) was called
 3815     (check-ints-equal *(edx+4) 2 "F - test-byte-values-in-unsupported-registers: exit status")
 3816     # don't restore from ebp
 3817     81 0/subop/add %esp 8/imm32
 3818     # . epilogue
 3819     5d/pop-to-ebp
 3820     c3/return
 3821 
 3822 # variables of type 'byte' _can_ be function args. They then occupy 4 bytes.
 3823 test-copy-byte-var-from-fn-arg:
 3824     # . prologue
 3825     55/push-ebp
 3826     89/<- %ebp 4/r32/esp
 3827     # setup
 3828     (clear-stream _test-input-stream)
 3829     (clear-stream $_test-input-buffered-file->buffer)
 3830     (clear-stream _test-output-stream)
 3831     (clear-stream $_test-output-buffered-file->buffer)
 3832     #
 3833     (write _test-input-stream "fn foo x: byte, y: int {\n")
 3834     (write _test-input-stream "  var a/eax: byte <- copy x\n")
 3835     (write _test-input-stream "  var b/eax: int <- copy y\n")
 3836     (write _test-input-stream "}\n")
 3837     # convert
 3838     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3839     (flush _test-output-buffered-file)
 3840 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 3846     # check output
 3847     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-copy-byte-from-fn-arg/0")
 3848     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-copy-byte-from-fn-arg/1")
 3849     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-copy-byte-from-fn-arg/2")
 3850     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-copy-byte-from-fn-arg/3")
 3851     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-copy-byte-from-fn-arg/4")
 3852     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-copy-byte-from-fn-arg/5")
 3853     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-copy-byte-from-fn-arg/6")
 3854     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-copy-byte-from-fn-arg/7")
 3855     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x0000000c) 0x00000000/r32"  "F - test-copy-byte-from-fn-arg/8")
 3856     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"   "F - test-copy-byte-from-fn-arg/9")
 3857     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-copy-byte-from-fn-arg/10")
 3858     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-copy-byte-from-fn-arg/11")
 3859     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-copy-byte-from-fn-arg/12")
 3860     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-copy-byte-from-fn-arg/13")
 3861     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-copy-byte-from-fn-arg/14")
 3862     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-copy-byte-from-fn-arg/15")
 3863     # . epilogue
 3864     89/<- %esp 5/r32/ebp
 3865     5d/pop-to-ebp
 3866     c3/return
 3867 
 3868 test-convert-compare-register-with-literal:
 3869     # . prologue
 3870     55/push-ebp
 3871     89/<- %ebp 4/r32/esp
 3872     # setup
 3873     (clear-stream _test-input-stream)
 3874     (clear-stream $_test-input-buffered-file->buffer)
 3875     (clear-stream _test-output-stream)
 3876     (clear-stream $_test-output-buffered-file->buffer)
 3877     #
 3878     (write _test-input-stream "fn foo {\n")
 3879     (write _test-input-stream "  var x/ecx: int <- copy 0\n")
 3880     (write _test-input-stream "  compare x, 0\n")
 3881     (write _test-input-stream "}\n")
 3882     # convert
 3883     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3884     (flush _test-output-buffered-file)
 3885 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 3891     # check output
 3892     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-compare-register-with-literal/0")
 3893     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-compare-register-with-literal/1")
 3894     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-compare-register-with-literal/2")
 3895     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-compare-register-with-literal/3")
 3896     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-compare-register-with-literal/4")
 3897     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-compare-register-with-literal/5")
 3898     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-compare-register-with-literal/6")
 3899     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-compare-register-with-literal/7")
 3900     (check-next-stream-line-equal _test-output-stream "    81 7/subop/compare %ecx 0/imm32"  "F - test-convert-compare-register-with-literal/8")
 3901     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-compare-register-with-literal/9")
 3902     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-compare-register-with-literal/10")
 3903     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-compare-register-with-literal/11")
 3904     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-compare-register-with-literal/12")
 3905     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-compare-register-with-literal/13")
 3906     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-compare-register-with-literal/14")
 3907     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-compare-register-with-literal/15")
 3908     # . epilogue
 3909     89/<- %esp 5/r32/ebp
 3910     5d/pop-to-ebp
 3911     c3/return
 3912 
 3913 test-convert-compare-byte-with-literal:
 3914     # . prologue
 3915     55/push-ebp
 3916     89/<- %ebp 4/r32/esp
 3917     # setup
 3918     (clear-stream _test-input-stream)
 3919     (clear-stream $_test-input-buffered-file->buffer)
 3920     (clear-stream _test-output-stream)
 3921     (clear-stream $_test-output-buffered-file->buffer)
 3922     #
 3923     (write _test-input-stream "fn foo {\n")
 3924     (write _test-input-stream "  var x/ecx: byte <- copy 0\n")
 3925     (write _test-input-stream "  compare x, 0\n")
 3926     (write _test-input-stream "}\n")
 3927     # convert
 3928     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3929     (flush _test-output-buffered-file)
 3930 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 3936     # no errors; output is identical to test-convert-compare-register-with-literal
 3937     # . epilogue
 3938     89/<- %esp 5/r32/ebp
 3939     5d/pop-to-ebp
 3940     c3/return
 3941 
 3942 test-unknown-variable:
 3943     # . prologue
 3944     55/push-ebp
 3945     89/<- %ebp 4/r32/esp
 3946     # setup
 3947     (clear-stream _test-input-stream)
 3948     (clear-stream $_test-input-buffered-file->buffer)
 3949     (clear-stream _test-output-stream)
 3950     (clear-stream $_test-output-buffered-file->buffer)
 3951     (clear-stream _test-error-stream)
 3952     (clear-stream $_test-error-buffered-file->buffer)
 3953     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3954     68/push 0/imm32
 3955     68/push 0/imm32
 3956     89/<- %edx 4/r32/esp
 3957     (tailor-exit-descriptor %edx 0x10)
 3958     #
 3959     (write _test-input-stream "fn foo {\n")
 3960     (write _test-input-stream "  compare x, 0\n")
 3961     (write _test-input-stream "}\n")
 3962     # convert
 3963     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3964     # registers except esp clobbered at this point
 3965     # restore ed
 3966     89/<- %edx 4/r32/esp
 3967     (flush _test-output-buffered-file)
 3968     (flush _test-error-buffered-file)
 3969 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3975     # check output
 3976     (check-stream-equal _test-output-stream  ""  "F - test-unknown-variable: output should be empty")
 3977     (check-next-stream-line-equal _test-error-stream  "fn foo: unknown variable 'x'"  "F - test-unknown-variable: error message")
 3978     # check that stop(1) was called
 3979     (check-ints-equal *(edx+4) 2 "F - test-unknown-variable: exit status")
 3980     # don't restore from ebp
 3981     81 0/subop/add %esp 8/imm32
 3982     # . epilogue
 3983     5d/pop-to-ebp
 3984     c3/return
 3985 
 3986 test-convert-function-with-local-var-in-block:
 3987     # . prologue
 3988     55/push-ebp
 3989     89/<- %ebp 4/r32/esp
 3990     # setup
 3991     (clear-stream _test-input-stream)
 3992     (clear-stream $_test-input-buffered-file->buffer)
 3993     (clear-stream _test-output-stream)
 3994     (clear-stream $_test-output-buffered-file->buffer)
 3995     #
 3996     (write _test-input-stream "fn foo {\n")
 3997     (write _test-input-stream "  {\n")
 3998     (write _test-input-stream "    var x: int\n")
 3999     (write _test-input-stream "    increment x\n")
 4000     (write _test-input-stream "  }\n")
 4001     (write _test-input-stream "}\n")
 4002     # convert
 4003     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4004     (flush _test-output-buffered-file)
 4005 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4011     # check output
 4012     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-block/0")
 4013     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-block/1")
 4014     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-block/2")
 4015     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-block/3")
 4016     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-block/4")
 4017     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-block/5")
 4018     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-local-var-in-block/6")
 4019     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-local-var-in-block/7")
 4020     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-local-var-in-block/8")
 4021     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-local-var-in-block/9")
 4022     (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")
 4023     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-local-var-in-block/11")
 4024     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-local-var-in-block/12")
 4025     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-block/13")
 4026     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-block/14")
 4027     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-block/15")
 4028     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-block/16")
 4029     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-block/17")
 4030     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-block/18")
 4031     # . epilogue
 4032     89/<- %esp 5/r32/ebp
 4033     5d/pop-to-ebp
 4034     c3/return
 4035 
 4036 test-convert-function-with-local-var-in-mem-after-block:
 4037     # . prologue
 4038     55/push-ebp
 4039     89/<- %ebp 4/r32/esp
 4040     # setup
 4041     (clear-stream _test-input-stream)
 4042     (clear-stream $_test-input-buffered-file->buffer)
 4043     (clear-stream _test-output-stream)
 4044     (clear-stream $_test-output-buffered-file->buffer)
 4045     #
 4046     (write _test-input-stream "fn foo {\n")
 4047     (write _test-input-stream "  {\n")
 4048     (write _test-input-stream "    var y: int\n")
 4049     (write _test-input-stream "  }\n")
 4050     (write _test-input-stream "  var x: int\n")
 4051     (write _test-input-stream "  increment x\n")
 4052     (write _test-input-stream "}\n")
 4053     # convert
 4054     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4055     (flush _test-output-buffered-file)
 4056 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4062     # check output
 4063     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-mem-after-block/0")
 4064     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-mem-after-block/1")
 4065     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-mem-after-block/2")
 4066     (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")
 4067     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-mem-after-block/4")
 4068     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-mem-after-block/5")
 4069     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-local-var-in-mem-after-block/6")
 4070     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-local-var-in-mem-after-block/7")
 4071     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-local-var-in-mem-after-block/8")
 4072     (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")
 4073     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-local-var-in-mem-after-block/10")
 4074     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-local-var-in-mem-after-block/11")
 4075     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-in-mem-after-block/12")
 4076     (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")
 4077     (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")
 4078     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-mem-after-block/15")
 4079     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-mem-after-block/16")
 4080     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-mem-after-block/17")
 4081     (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")
 4082     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-mem-after-block/19")
 4083     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-mem-after-block/20")
 4084     # . epilogue
 4085     89/<- %esp 5/r32/ebp
 4086     5d/pop-to-ebp
 4087     c3/return
 4088 
 4089 test-convert-function-with-local-var-in-named-block:
 4090     # . prologue
 4091     55/push-ebp
 4092     89/<- %ebp 4/r32/esp
 4093     # setup
 4094     (clear-stream _test-input-stream)
 4095     (clear-stream $_test-input-buffered-file->buffer)
 4096     (clear-stream _test-output-stream)
 4097     (clear-stream $_test-output-buffered-file->buffer)
 4098     #
 4099     (write _test-input-stream "fn foo {\n")
 4100     (write _test-input-stream "  $bar: {\n")
 4101     (write _test-input-stream "    var x: int\n")
 4102     (write _test-input-stream "    increment x\n")
 4103     (write _test-input-stream "  }\n")
 4104     (write _test-input-stream "}\n")
 4105     # convert
 4106     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4107     (flush _test-output-buffered-file)
 4108 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4114     # check output
 4115     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-named-block/0")
 4116     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-named-block/1")
 4117     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-named-block/2")
 4118     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-named-block/3")
 4119     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-named-block/4")
 4120     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-named-block/5")
 4121     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-local-var-in-named-block/6")
 4122     (check-next-stream-line-equal _test-output-stream "$bar:loop:"              "F - test-convert-function-with-local-var-in-named-block/7")
 4123     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-local-var-in-named-block/8")
 4124     (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")
 4125     (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")
 4126     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-local-var-in-named-block/11")
 4127     (check-next-stream-line-equal _test-output-stream "$bar:break:"             "F - test-convert-function-with-local-var-in-named-block/12")
 4128     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-named-block/13")
 4129     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-named-block/14")
 4130     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-named-block/15")
 4131     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-named-block/16")
 4132     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-named-block/17")
 4133     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-named-block/18")
 4134     # . epilogue
 4135     89/<- %esp 5/r32/ebp
 4136     5d/pop-to-ebp
 4137     c3/return
 4138 
 4139 test-unknown-variable-in-named-block:
 4140     # . prologue
 4141     55/push-ebp
 4142     89/<- %ebp 4/r32/esp
 4143     # setup
 4144     (clear-stream _test-input-stream)
 4145     (clear-stream $_test-input-buffered-file->buffer)
 4146     (clear-stream _test-output-stream)
 4147     (clear-stream $_test-output-buffered-file->buffer)
 4148     (clear-stream _test-error-stream)
 4149     (clear-stream $_test-error-buffered-file->buffer)
 4150     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 4151     68/push 0/imm32
 4152     68/push 0/imm32
 4153     89/<- %edx 4/r32/esp
 4154     (tailor-exit-descriptor %edx 0x10)
 4155     #
 4156     (write _test-input-stream "fn foo {\n")
 4157     (write _test-input-stream "  $a: {\n")
 4158     (write _test-input-stream "    compare x, 0\n")
 4159     (write _test-input-stream "  }\n")
 4160     (write _test-input-stream "}\n")
 4161     # convert
 4162     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 4163     # registers except esp clobbered at this point
 4164     # restore ed
 4165     89/<- %edx 4/r32/esp
 4166     (flush _test-output-buffered-file)
 4167     (flush _test-error-buffered-file)
 4168 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 4174     # check output
 4175     (check-stream-equal _test-output-stream  ""  "F - test-unknown-variable-in-named-block: output should be empty")
 4176     (check-next-stream-line-equal _test-error-stream  "fn foo: unknown variable 'x'"  "F - test-unknown-variable-in-named-block: error message")
 4177     # check that stop(1) was called
 4178     (check-ints-equal *(edx+4) 2 "F - test-unknown-variable-in-named-block: exit status")
 4179     # don't restore from ebp
 4180     81 0/subop/add %esp 8/imm32
 4181     # . epilogue
 4182     5d/pop-to-ebp
 4183     c3/return
 4184 
 4185 test-always-shadow-outermost-reg-vars-in-function:
 4186     # . prologue
 4187     55/push-ebp
 4188     89/<- %ebp 4/r32/esp
 4189     # setup
 4190     (clear-stream _test-input-stream)
 4191     (clear-stream $_test-input-buffered-file->buffer)
 4192     (clear-stream _test-output-stream)
 4193     (clear-stream $_test-output-buffered-file->buffer)
 4194     #
 4195     (write _test-input-stream "fn foo {\n")
 4196     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 4197     (write _test-input-stream "}\n")
 4198     # convert
 4199     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4200     (flush _test-output-buffered-file)
 4201 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4207     # check output
 4208     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-always-shadow-outermost-reg-vars-in-function/0")
 4209     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-always-shadow-outermost-reg-vars-in-function/1")
 4210     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-always-shadow-outermost-reg-vars-in-function/2")
 4211     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-always-shadow-outermost-reg-vars-in-function/3")
 4212     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-always-shadow-outermost-reg-vars-in-function/4")
 4213     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-always-shadow-outermost-reg-vars-in-function/5")
 4214     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-compare-register-with-literal/6")
 4215     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-always-shadow-outermost-reg-vars-in-function/8")
 4216     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-compare-register-with-literal/9")
 4217     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-always-shadow-outermost-reg-vars-in-function/12")
 4218     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-always-shadow-outermost-reg-vars-in-function/13")
 4219     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-always-shadow-outermost-reg-vars-in-function/14")
 4220     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-always-shadow-outermost-reg-vars-in-function/15")
 4221     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-always-shadow-outermost-reg-vars-in-function/16")
 4222     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-always-shadow-outermost-reg-vars-in-function/17")
 4223     # . epilogue
 4224     89/<- %esp 5/r32/ebp
 4225     5d/pop-to-ebp
 4226     c3/return
 4227 
 4228 test-shadow-local:
 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 "  var x/ecx: int <- copy 3\n")
 4240     (write _test-input-stream "  {\n")
 4241     (write _test-input-stream "    var y/ecx: int <- copy 4\n")
 4242     (write _test-input-stream "  }\n")
 4243     (write _test-input-stream "  x <- increment\n")
 4244     (write _test-input-stream "}\n")
 4245     # convert
 4246     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4247     (flush _test-output-buffered-file)
 4248 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4254     # check output
 4255     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-shadow-local/0")
 4256     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-shadow-local/1")
 4257     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-shadow-local/2")
 4258     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-shadow-local/3")
 4259     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-shadow-local/4")
 4260     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-shadow-local/5")
 4261     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-shadow-local/6")
 4262     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-shadow-local/7")
 4263     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-shadow-local/8")
 4264     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-shadow-local/9")
 4265     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %ecx"  "F - test-shadow-local/10")
 4266     (check-next-stream-line-equal _test-output-stream "      b9/copy-to-ecx 4/imm32"  "F - test-shadow-local/11")
 4267     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %ecx" "F - test-shadow-local/12")
 4268     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-shadow-local/13")
 4269     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-shadow-local/14")
 4270     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-shadow-local/15")
 4271     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-shadow-local/16")
 4272     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-shadow-local/17")
 4273     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-shadow-local/18")
 4274     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-shadow-local/19")
 4275     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-shadow-local/20")
 4276     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-shadow-local/21")
 4277     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-shadow-local/22")
 4278     # . epilogue
 4279     89/<- %esp 5/r32/ebp
 4280     5d/pop-to-ebp
 4281     c3/return
 4282 
 4283 test-shadow-name:
 4284     # . prologue
 4285     55/push-ebp
 4286     89/<- %ebp 4/r32/esp
 4287     # setup
 4288     (clear-stream _test-input-stream)
 4289     (clear-stream $_test-input-buffered-file->buffer)
 4290     (clear-stream _test-output-stream)
 4291     (clear-stream $_test-output-buffered-file->buffer)
 4292     #
 4293     (write _test-input-stream "fn foo {\n")
 4294     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 4295     (write _test-input-stream "  {\n")
 4296     (write _test-input-stream "    var x/edx: int <- copy 4\n")
 4297     (write _test-input-stream "  }\n")
 4298     (write _test-input-stream "  x <- increment\n")
 4299     (write _test-input-stream "}\n")
 4300     # convert
 4301     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4302     (flush _test-output-buffered-file)
 4303 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4309     # check output
 4310     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-shadow-name/0")
 4311     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-shadow-name/1")
 4312     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-shadow-name/2")
 4313     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-shadow-name/3")
 4314     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-shadow-name/4")
 4315     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-shadow-name/5")
 4316     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-shadow-name/6")
 4317     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-shadow-name/7")
 4318     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-shadow-name/8")
 4319     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-shadow-name/9")
 4320     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %edx"  "F - test-shadow-name/10")
 4321     (check-next-stream-line-equal _test-output-stream "      ba/copy-to-edx 4/imm32"  "F - test-shadow-name/11")
 4322     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %edx" "F - test-shadow-name/12")
 4323     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-shadow-name/13")
 4324     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-shadow-name/14")
 4325     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-shadow-name/15")
 4326     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-shadow-name/16")
 4327     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-shadow-name/17")
 4328     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-shadow-name/18")
 4329     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-shadow-name/19")
 4330     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-shadow-name/20")
 4331     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-shadow-name/21")
 4332     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-shadow-name/22")
 4333     # . epilogue
 4334     89/<- %esp 5/r32/ebp
 4335     5d/pop-to-ebp
 4336     c3/return
 4337 
 4338 test-shadow-name-2:
 4339     # . prologue
 4340     55/push-ebp
 4341     89/<- %ebp 4/r32/esp
 4342     # setup
 4343     (clear-stream _test-input-stream)
 4344     (clear-stream $_test-input-buffered-file->buffer)
 4345     (clear-stream _test-output-stream)
 4346     (clear-stream $_test-output-buffered-file->buffer)
 4347     #
 4348     (write _test-input-stream "fn foo {\n")
 4349     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 4350     (write _test-input-stream "  {\n")
 4351     (write _test-input-stream "    var x/edx: int <- copy 4\n")
 4352     (write _test-input-stream "    var y/ecx: int <- copy 5\n")
 4353     (write _test-input-stream "  }\n")
 4354     (write _test-input-stream "  x <- increment\n")
 4355     (write _test-input-stream "}\n")
 4356     # convert
 4357     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4358     (flush _test-output-buffered-file)
 4359 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4365     # check output
 4366     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-shadow-name-2/0")
 4367     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-shadow-name-2/1")
 4368     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-shadow-name-2/2")
 4369     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-shadow-name-2/3")
 4370     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-shadow-name-2/4")
 4371     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-shadow-name-2/5")
 4372     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-shadow-name-2/6")
 4373     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-shadow-name-2/7")
 4374     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-shadow-name-2/8")
 4375     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-shadow-name-2/9")
 4376     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %edx"  "F - test-shadow-name-2/10")
 4377     (check-next-stream-line-equal _test-output-stream "      ba/copy-to-edx 4/imm32"  "F - test-shadow-name-2/11")
 4378     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %ecx"  "F - test-shadow-name-2/12")
 4379     (check-next-stream-line-equal _test-output-stream "      b9/copy-to-ecx 5/imm32"  "F - test-shadow-name-2/13")
 4380     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %ecx" "F - test-shadow-name-2/14")
 4381     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %edx" "F - test-shadow-name-2/15")
 4382     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-shadow-name-2/16")
 4383     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-shadow-name-2/17")
 4384     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-shadow-name-2/18")
 4385     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-shadow-name-2/19")
 4386     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-shadow-name-2/20")
 4387     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-shadow-name-2/21")
 4388     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-shadow-name-2/22")
 4389     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-shadow-name-2/23")
 4390     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-shadow-name-2/24")
 4391     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-shadow-name-2/25")
 4392     # . epilogue
 4393     89/<- %esp 5/r32/ebp
 4394     5d/pop-to-ebp
 4395     c3/return
 4396 
 4397 test-do-not-spill-same-register-in-block:
 4398     # . prologue
 4399     55/push-ebp
 4400     89/<- %ebp 4/r32/esp
 4401     # setup
 4402     (clear-stream _test-input-stream)
 4403     (clear-stream $_test-input-buffered-file->buffer)
 4404     (clear-stream _test-output-stream)
 4405     (clear-stream $_test-output-buffered-file->buffer)
 4406     #
 4407     (write _test-input-stream "fn foo {\n")
 4408     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 4409     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
 4410     (write _test-input-stream "  y <- increment\n")
 4411     (write _test-input-stream "}\n")
 4412     # convert
 4413     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4414     (flush _test-output-buffered-file)
 4415 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4421     # check output
 4422     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-do-not-spill-same-register-in-block/0")
 4423     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-do-not-spill-same-register-in-block/1")
 4424     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-do-not-spill-same-register-in-block/2")
 4425     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-do-not-spill-same-register-in-block/3")
 4426     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-do-not-spill-same-register-in-block/4")
 4427     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-do-not-spill-same-register-in-block/5")
 4428     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-do-not-spill-same-register-in-block/6")
 4429     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-do-not-spill-same-register-in-block/7")
 4430     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 4/imm32"  "F - test-do-not-spill-same-register-in-block/8")
 4431     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-do-not-spill-same-register-in-block/9")
 4432     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-do-not-spill-same-register-in-block/10")
 4433     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-do-not-spill-same-register-in-block/11")
 4434     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-do-not-spill-same-register-in-block/12")
 4435     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-do-not-spill-same-register-in-block/13")
 4436     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-do-not-spill-same-register-in-block/14")
 4437     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-do-not-spill-same-register-in-block/15")
 4438     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-do-not-spill-same-register-in-block/16")
 4439     # . epilogue
 4440     89/<- %esp 5/r32/ebp
 4441     5d/pop-to-ebp
 4442     c3/return
 4443 
 4444 test-spill-different-register-in-block:
 4445     # . prologue
 4446     55/push-ebp
 4447     89/<- %ebp 4/r32/esp
 4448     # setup
 4449     (clear-stream _test-input-stream)
 4450     (clear-stream $_test-input-buffered-file->buffer)
 4451     (clear-stream _test-output-stream)
 4452     (clear-stream $_test-output-buffered-file->buffer)
 4453     #
 4454     (write _test-input-stream "fn foo {\n")
 4455     (write _test-input-stream "  var x/eax: int <- copy 3\n")
 4456     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
 4457     (write _test-input-stream "  y <- increment\n")
 4458     (write _test-input-stream "}\n")
 4459     # convert
 4460     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4461     (flush _test-output-buffered-file)
 4462 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4468     # check output
 4469     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-spill-different-register-in-block/0")
 4470     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-spill-different-register-in-block/1")
 4471     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-spill-different-register-in-block/2")
 4472     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-spill-different-register-in-block/3")
 4473     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-spill-different-register-in-block/4")
 4474     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-spill-different-register-in-block/5")
 4475     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-spill-different-register-in-block/6")
 4476     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 3/imm32"  "F - test-spill-different-register-in-block/7")
 4477     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-spill-different-register-in-block/8")
 4478     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 4/imm32"  "F - test-spill-different-register-in-block/9")
 4479     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-spill-different-register-in-block/10")
 4480     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-spill-different-register-in-block/11")
 4481     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-spill-different-register-in-block/12")
 4482     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-spill-different-register-in-block/13")
 4483     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-spill-different-register-in-block/14")
 4484     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-spill-different-register-in-block/15")
 4485     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-spill-different-register-in-block/16")
 4486     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-spill-different-register-in-block/17")
 4487     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-spill-different-register-in-block/18")
 4488     # . epilogue
 4489     89/<- %esp 5/r32/ebp
 4490     5d/pop-to-ebp
 4491     c3/return
 4492 
 4493 test-convert-function-with-branches-in-block:
 4494     # . prologue
 4495     55/push-ebp
 4496     89/<- %ebp 4/r32/esp
 4497     # setup
 4498     (clear-stream _test-input-stream)
 4499     (clear-stream $_test-input-buffered-file->buffer)
 4500     (clear-stream _test-output-stream)
 4501     (clear-stream $_test-output-buffered-file->buffer)
 4502     #
 4503     (write _test-input-stream "fn foo x: int {\n")
 4504     (write _test-input-stream "  {\n")
 4505     (write _test-input-stream "    break-if->=\n")
 4506     (write _test-input-stream "    loop-if-addr<\n")
 4507     (write _test-input-stream "    increment x\n")
 4508     (write _test-input-stream "    loop\n")
 4509     (write _test-input-stream "  }\n")
 4510     (write _test-input-stream "}\n")
 4511     # convert
 4512     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4513     (flush _test-output-buffered-file)
 4514 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4520     # check output
 4521     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-in-block/0")
 4522     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-in-block/1")
 4523     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-in-block/2")
 4524     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-in-block/3")
 4525     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-in-block/4")
 4526     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-in-block/5")
 4527     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-in-block/6")
 4528     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-branches-in-block/7")
 4529     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-block/8")
 4530     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-in-block/9")
 4531     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-with-branches-in-block/10")
 4532     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-block/11")
 4533     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-block/12")
 4534     (check-next-stream-line-equal _test-output-stream "        0f 83/jump-if-addr>= break/disp32"  "F - test-convert-function-with-branches-in-block/13")
 4535     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:loop/disp32"  "F - test-convert-function-with-branches-in-block/14")
 4536     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-block/15")
 4537     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0x00000008)"  "F - test-convert-function-with-branches-in-block/16")
 4538     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"  "F - test-convert-function-with-branches-in-block/17")
 4539     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-in-block/18")
 4540     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-branches-in-block/19")
 4541     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-in-block/20")
 4542     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-in-block/21")
 4543     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-in-block/22")
 4544     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-in-block/23")
 4545     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-in-block/24")
 4546     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-in-block/25")
 4547     # . epilogue
 4548     89/<- %esp 5/r32/ebp
 4549     5d/pop-to-ebp
 4550     c3/return
 4551 
 4552 test-convert-function-with-branches-in-block-2:
 4553     # . prologue
 4554     55/push-ebp
 4555     89/<- %ebp 4/r32/esp
 4556     # setup
 4557     (clear-stream _test-input-stream)
 4558     (clear-stream $_test-input-buffered-file->buffer)
 4559     (clear-stream _test-output-stream)
 4560     (clear-stream $_test-output-buffered-file->buffer)
 4561     #
 4562     (write _test-input-stream "fn foo x: int {\n")
 4563     (write _test-input-stream "  {\n")
 4564     (write _test-input-stream "    break-if->=\n")
 4565     (write _test-input-stream "    loop-if-float<\n")
 4566     (write _test-input-stream "    increment x\n")
 4567     (write _test-input-stream "    loop\n")
 4568     (write _test-input-stream "  }\n")
 4569     (write _test-input-stream "}\n")
 4570     # convert
 4571     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4572     (flush _test-output-buffered-file)
 4573 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4579     # check output
 4580     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-in-block/0")
 4581     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-in-block/1")
 4582     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-in-block/2")
 4583     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-in-block/3")
 4584     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-in-block/4")
 4585     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-in-block/5")
 4586     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-in-block/6")
 4587     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-branches-in-block/7")
 4588     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-block/8")
 4589     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-in-block/9")
 4590     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-with-branches-in-block/10")
 4591     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-block/11")
 4592     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-block/12")
 4593     (check-next-stream-line-equal _test-output-stream "        0f 83/jump-if-addr>= break/disp32"  "F - test-convert-function-with-branches-in-block/13")
 4594     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:loop/disp32"  "F - test-convert-function-with-branches-in-block/14")
 4595     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-block/15")
 4596     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0x00000008)"  "F - test-convert-function-with-branches-in-block/16")
 4597     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"  "F - test-convert-function-with-branches-in-block/17")
 4598     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-in-block/18")
 4599     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-branches-in-block/19")
 4600     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-in-block/20")
 4601     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-in-block/21")
 4602     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-in-block/22")
 4603     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-in-block/23")
 4604     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-in-block/24")
 4605     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-in-block/25")
 4606     # . epilogue
 4607     89/<- %esp 5/r32/ebp
 4608     5d/pop-to-ebp
 4609     c3/return
 4610 
 4611 test-convert-function-with-branches-in-named-block:
 4612     # . prologue
 4613     55/push-ebp
 4614     89/<- %ebp 4/r32/esp
 4615     # setup
 4616     (clear-stream _test-input-stream)
 4617     (clear-stream $_test-input-buffered-file->buffer)
 4618     (clear-stream _test-output-stream)
 4619     (clear-stream $_test-output-buffered-file->buffer)
 4620     #
 4621     (write _test-input-stream "fn foo x: int {\n")
 4622     (write _test-input-stream "  $bar: {\n")
 4623     (write _test-input-stream "    break-if->= $bar\n")
 4624     (write _test-input-stream "    loop-if-addr< $bar\n")
 4625     (write _test-input-stream "    increment x\n")
 4626     (write _test-input-stream "    loop\n")
 4627     (write _test-input-stream "  }\n")
 4628     (write _test-input-stream "}\n")
 4629     # convert
 4630     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4631     (flush _test-output-buffered-file)
 4632 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4638     # check output
 4639     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-in-named-block/0")
 4640     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-in-named-block/1")
 4641     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-in-named-block/2")
 4642     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-in-named-block/3")
 4643     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-in-named-block/4")
 4644     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-in-named-block/5")
 4645     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-in-named-block/6")
 4646     (check-next-stream-line-equal _test-output-stream "$bar:loop:"              "F - test-convert-function-with-branches-in-named-block/7")
 4647     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-named-block/8")
 4648     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-in-named-block/9")
 4649     (check-next-stream-line-equal _test-output-stream "        e9/jump $bar:break/disp32"  "F - test-convert-function-with-branches-in-named-block/10")
 4650     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-named-block/11")
 4651     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-named-block/12")
 4652     (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")
 4653     (check-next-stream-line-equal _test-output-stream "        e9/jump $bar:loop/disp32"  "F - test-convert-function-with-branches-in-named-block/14")
 4654     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-named-block/15")
 4655     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0x00000008)"  "F - test-convert-function-with-branches-in-named-block/16")
 4656     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"   "F - test-convert-function-with-branches-in-named-block/17")
 4657     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-in-named-block/18")
 4658     (check-next-stream-line-equal _test-output-stream "$bar:break:"             "F - test-convert-function-with-branches-in-named-block/19")
 4659     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-in-named-block/20")
 4660     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-in-named-block/21")
 4661     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-in-named-block/22")
 4662     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-in-named-block/23")
 4663     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-in-named-block/24")
 4664     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-in-named-block/25")
 4665     # . epilogue
 4666     89/<- %esp 5/r32/ebp
 4667     5d/pop-to-ebp
 4668     c3/return
 4669 
 4670 test-convert-function-with-var-in-nested-block:
 4671     # . prologue
 4672     55/push-ebp
 4673     89/<- %ebp 4/r32/esp
 4674     # setup
 4675     (clear-stream _test-input-stream)
 4676     (clear-stream $_test-input-buffered-file->buffer)
 4677     (clear-stream _test-output-stream)
 4678     (clear-stream $_test-output-buffered-file->buffer)
 4679     #
 4680     (write _test-input-stream "fn foo x: int {\n")
 4681     (write _test-input-stream "  {\n")
 4682     (write _test-input-stream "    {\n")
 4683     (write _test-input-stream "      var x: int\n")
 4684     (write _test-input-stream "      increment x\n")
 4685     (write _test-input-stream "    }\n")
 4686     (write _test-input-stream "  }\n")
 4687     (write _test-input-stream "}\n")
 4688     # convert
 4689     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4690     (flush _test-output-buffered-file)
 4691 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4697     # check output
 4698     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-var-in-nested-block/0")
 4699     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-var-in-nested-block/1")
 4700     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-var-in-nested-block/2")
 4701     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-var-in-nested-block/3")
 4702     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-var-in-nested-block/4")
 4703     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-var-in-nested-block/5")
 4704     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-var-in-nested-block/6")
 4705     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-var-in-nested-block/7")
 4706     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-var-in-nested-block/8")
 4707     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-var-in-nested-block/9")
 4708     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-var-in-nested-block/10")
 4709     (check-next-stream-line-equal _test-output-stream "        ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-var-in-nested-block/11")
 4710     (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")
 4711     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-var-in-nested-block/13")
 4712     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-var-in-nested-block/14")
 4713     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-var-in-nested-block/15")
 4714     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-var-in-nested-block/16")
 4715     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-var-in-nested-block/17")
 4716     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-var-in-nested-block/18")
 4717     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-var-in-nested-block/19")
 4718     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-var-in-nested-block/20")
 4719     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-var-in-nested-block/21")
 4720     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-var-in-nested-block/22")
 4721     # . epilogue
 4722     89/<- %esp 5/r32/ebp
 4723     5d/pop-to-ebp
 4724     c3/return
 4725 
 4726 test-convert-function-with-multiple-vars-in-nested-blocks:
 4727     # . prologue
 4728     55/push-ebp
 4729     89/<- %ebp 4/r32/esp
 4730     # setup
 4731     (clear-stream _test-input-stream)
 4732     (clear-stream $_test-input-buffered-file->buffer)
 4733     (clear-stream _test-output-stream)
 4734     (clear-stream $_test-output-buffered-file->buffer)
 4735     #
 4736     (write _test-input-stream "fn foo x: int {\n")
 4737     (write _test-input-stream "  {\n")
 4738     (write _test-input-stream "    var x/eax: int <- copy 0\n")
 4739     (write _test-input-stream "    {\n")
 4740     (write _test-input-stream "      var y: int\n")
 4741     (write _test-input-stream "      x <- add y\n")
 4742     (write _test-input-stream "    }\n")
 4743     (write _test-input-stream "  }\n")
 4744     (write _test-input-stream "}\n")
 4745     # convert
 4746     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4747     (flush _test-output-buffered-file)
 4748 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4754     # check output
 4755     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-multiple-vars-in-nested-blocks/0")
 4756     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-multiple-vars-in-nested-blocks/1")
 4757     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-multiple-vars-in-nested-blocks/2")
 4758     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/3")
 4759     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-multiple-vars-in-nested-blocks/4")
 4760     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/5")
 4761     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-multiple-vars-in-nested-blocks/6")
 4762     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/7")
 4763     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %eax"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/8")
 4764     (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")
 4765     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-multiple-vars-in-nested-blocks/10")
 4766     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/11")
 4767     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-multiple-vars-in-nested-blocks/12")
 4768     (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")
 4769     (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")
 4770     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-multiple-vars-in-nested-blocks/15")
 4771     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/16")
 4772     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %eax"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/17")
 4773     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-multiple-vars-in-nested-blocks/18")
 4774     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/19")
 4775     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-multiple-vars-in-nested-blocks/20")
 4776     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/21")
 4777     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-multiple-vars-in-nested-blocks/22")
 4778     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/23")
 4779     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-multiple-vars-in-nested-blocks/24")
 4780     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-multiple-vars-in-nested-blocks/25")
 4781     # . epilogue
 4782     89/<- %esp 5/r32/ebp
 4783     5d/pop-to-ebp
 4784     c3/return
 4785 
 4786 test-convert-function-with-branches-and-local-vars:
 4787     # A conditional 'break' after a 'var' in a block is converted into a
 4788     # nested block that performs all necessary cleanup before jumping. This
 4789     # results in some ugly code duplication.
 4790     # . prologue
 4791     55/push-ebp
 4792     89/<- %ebp 4/r32/esp
 4793     # setup
 4794     (clear-stream _test-input-stream)
 4795     (clear-stream $_test-input-buffered-file->buffer)
 4796     (clear-stream _test-output-stream)
 4797     (clear-stream $_test-output-buffered-file->buffer)
 4798     #
 4799     (write _test-input-stream "fn foo {\n")
 4800     (write _test-input-stream "  {\n")
 4801     (write _test-input-stream "    var x: int\n")
 4802     (write _test-input-stream "    break-if->=\n")
 4803     (write _test-input-stream "    increment x\n")
 4804     (write _test-input-stream "  }\n")
 4805     (write _test-input-stream "}\n")
 4806     # convert
 4807     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4808     (flush _test-output-buffered-file)
 4809 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4815     # check output
 4816     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-and-local-vars/0")
 4817     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-and-local-vars/1")
 4818     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-and-local-vars/2")
 4819     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-and-local-vars/3")
 4820     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-and-local-vars/4")
 4821     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-and-local-vars/5")
 4822     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-and-local-vars/6")
 4823     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-branches-and-local-vars/7")
 4824     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-branches-and-local-vars/8")
 4825     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-and-local-vars/9")
 4826     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-and-local-vars/10")
 4827     (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")
 4828     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-with-branches-and-local-vars/12")
 4829     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-and-local-vars/13")
 4830     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-branches-and-local-vars/14")
 4831     (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")
 4832     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-and-local-vars/16")
 4833     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-branches-and-local-vars/17")
 4834     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-and-local-vars/18")
 4835     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-and-local-vars/19")
 4836     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-and-local-vars/20")
 4837     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-and-local-vars/21")
 4838     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-and-local-vars/22")
 4839     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-and-local-vars/23")
 4840     # . epilogue
 4841     89/<- %esp 5/r32/ebp
 4842     5d/pop-to-ebp
 4843     c3/return
 4844 
 4845 test-convert-function-with-conditional-loops-and-local-vars:
 4846     # A conditional 'loop' after a 'var' in a block is converted into a nested
 4847     # block that performs all necessary cleanup before jumping. This results
 4848     # in some ugly code duplication.
 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 "  {\n")
 4860     (write _test-input-stream "    var x: int\n")
 4861     (write _test-input-stream "    loop-if->=\n")
 4862     (write _test-input-stream "    increment x\n")
 4863     (write _test-input-stream "  }\n")
 4864     (write _test-input-stream "}\n")
 4865     # convert
 4866     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4867     (flush _test-output-buffered-file)
 4868 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4874     # check output
 4875     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-conditional-loops-and-local-vars/0")
 4876     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-conditional-loops-and-local-vars/1")
 4877     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-conditional-loops-and-local-vars/2")
 4878     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-conditional-loops-and-local-vars/3")
 4879     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-conditional-loops-and-local-vars/4")
 4880     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-conditional-loops-and-local-vars/5")
 4881     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-conditional-loops-and-local-vars/6")
 4882     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-conditional-loops-and-local-vars/7")
 4883     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-conditional-loops-and-local-vars/8")
 4884     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-conditional-loops-and-local-vars/9")
 4885     (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")
 4886     (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")
 4887     (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")
 4888     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-conditional-loops-and-local-vars/13")
 4889     (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")
 4890     (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")
 4891     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-conditional-loops-and-local-vars/16")
 4892     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-conditional-loops-and-local-vars/17")
 4893     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-conditional-loops-and-local-vars/18")
 4894     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-conditional-loops-and-local-vars/19")
 4895     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-conditional-loops-and-local-vars/20")
 4896     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-conditional-loops-and-local-vars/21")
 4897     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-conditional-loops-and-local-vars/22")
 4898     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-conditional-loops-and-local-vars/23")
 4899     # . epilogue
 4900     89/<- %esp 5/r32/ebp
 4901     5d/pop-to-ebp
 4902     c3/return
 4903 
 4904 test-convert-function-with-unconditional-loops-and-local-vars:
 4905     # An unconditional 'loop' after a 'var' in a block is emitted _after_ the
 4906     # regular block cleanup. Any instructions after 'loop' are dead and
 4907     # therefore skipped.
 4908     # . prologue
 4909     55/push-ebp
 4910     89/<- %ebp 4/r32/esp
 4911     # setup
 4912     (clear-stream _test-input-stream)
 4913     (clear-stream $_test-input-buffered-file->buffer)
 4914     (clear-stream _test-output-stream)
 4915     (clear-stream $_test-output-buffered-file->buffer)
 4916     #
 4917     (write _test-input-stream "fn foo {\n")
 4918     (write _test-input-stream "  {\n")
 4919     (write _test-input-stream "    var x: int\n")
 4920     (write _test-input-stream "    loop\n")
 4921     (write _test-input-stream "    increment x\n")
 4922     (write _test-input-stream "  }\n")
 4923     (write _test-input-stream "}\n")
 4924     # convert
 4925     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4926     (flush _test-output-buffered-file)
 4927 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4933     # check output
 4934     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-unconditional-loops-and-local-vars/0")
 4935     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-unconditional-loops-and-local-vars/1")
 4936     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-unconditional-loops-and-local-vars/2")
 4937     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-unconditional-loops-and-local-vars/3")
 4938     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-unconditional-loops-and-local-vars/4")
 4939     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-unconditional-loops-and-local-vars/5")
 4940     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-unconditional-loops-and-local-vars/6")
 4941     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-unconditional-loops-and-local-vars/7")
 4942     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-unconditional-loops-and-local-vars/8")
 4943     (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")
 4944     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"  "F - test-convert-function-with-unconditional-loops-and-local-vars/10")
 4945     # not emitted:                                           ff 0/subop/increment *(ebp+0xfffffffc)
 4946     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-unconditional-loops-and-local-vars/11")
 4947     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-unconditional-loops-and-local-vars/12")
 4948     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-unconditional-loops-and-local-vars/13")
 4949     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-unconditional-loops-and-local-vars/14")
 4950     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-unconditional-loops-and-local-vars/15")
 4951     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-unconditional-loops-and-local-vars/16")
 4952     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-unconditional-loops-and-local-vars/17")
 4953     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-unconditional-loops-and-local-vars/18")
 4954     # . epilogue
 4955     89/<- %esp 5/r32/ebp
 4956     5d/pop-to-ebp
 4957     c3/return
 4958 
 4959 test-convert-function-with-branches-and-loops-and-local-vars:
 4960     # . prologue
 4961     55/push-ebp
 4962     89/<- %ebp 4/r32/esp
 4963     # setup
 4964     (clear-stream _test-input-stream)
 4965     (clear-stream $_test-input-buffered-file->buffer)
 4966     (clear-stream _test-output-stream)
 4967     (clear-stream $_test-output-buffered-file->buffer)
 4968     #
 4969     (write _test-input-stream "fn foo {\n")
 4970     (write _test-input-stream "  {\n")
 4971     (write _test-input-stream "    var x: int\n")
 4972     (write _test-input-stream "    break-if->=\n")
 4973     (write _test-input-stream "    increment x\n")
 4974     (write _test-input-stream "    loop\n")
 4975     (write _test-input-stream "  }\n")
 4976     (write _test-input-stream "}\n")
 4977     # convert
 4978     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4979     (flush _test-output-buffered-file)
 4980 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4986     # check output
 4987     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-and-loops-and-local-vars/0")
 4988     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-and-loops-and-local-vars/1")
 4989     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-and-loops-and-local-vars/2")
 4990     (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")
 4991     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-and-loops-and-local-vars/4")
 4992     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-and-loops-and-local-vars/5")
 4993     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-and-loops-and-local-vars/6")
 4994     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-branches-and-loops-and-local-vars/7")
 4995     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-branches-and-loops-and-local-vars/8")
 4996     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-and-loops-and-local-vars/9")
 4997     (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")
 4998     (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")
 4999     (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")
 5000     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-and-loops-and-local-vars/13")
 5001     (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")
 5002     (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")
 5003     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"  "F - test-convert-function-with-branches-and-loops-and-local-vars/16")
 5004     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-and-loops-and-local-vars/17")
 5005     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-branches-and-loops-and-local-vars/18")
 5006     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-and-loops-and-local-vars/19")
 5007     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-and-loops-and-local-vars/20")
 5008     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-and-loops-and-local-vars/21")
 5009     (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")
 5010     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-and-loops-and-local-vars/23")
 5011     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-and-loops-and-local-vars/24")
 5012     # . epilogue
 5013     89/<- %esp 5/r32/ebp
 5014     5d/pop-to-ebp
 5015     c3/return
 5016 
 5017 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars:
 5018     # . prologue
 5019     55/push-ebp
 5020     89/<- %ebp 4/r32/esp
 5021     # setup
 5022     (clear-stream _test-input-stream)
 5023     (clear-stream $_test-input-buffered-file->buffer)
 5024     (clear-stream _test-output-stream)
 5025     (clear-stream $_test-output-buffered-file->buffer)
 5026     #
 5027     (write _test-input-stream "fn foo {\n")
 5028     (write _test-input-stream "  a: {\n")
 5029     (write _test-input-stream "    var x: int\n")
 5030     (write _test-input-stream "    {\n")
 5031     (write _test-input-stream "      var y: int\n")
 5032     (write _test-input-stream "      break-if->= a\n")
 5033     (write _test-input-stream "      increment x\n")
 5034     (write _test-input-stream "      loop\n")
 5035     (write _test-input-stream "    }\n")
 5036     (write _test-input-stream "  }\n")
 5037     (write _test-input-stream "}\n")
 5038     # convert
 5039     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5040     (flush _test-output-buffered-file)
 5041 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5047     # check output
 5048     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/0")
 5049     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/1")
 5050     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/2")
 5051     (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")
 5052     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/4")
 5053     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/5")
 5054     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/6")
 5055     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/7")
 5056     (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")
 5057     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/9")
 5058     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/10")
 5059     (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")
 5060     (check-next-stream-line-equal _test-output-stream "        {"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/12")
 5061     (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")
 5062     (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")
 5063     (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")
 5064     (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")
 5065     (check-next-stream-line-equal _test-output-stream "        }"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/17")
 5066     (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")
 5067     (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")
 5068     (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")
 5069     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/21")
 5070     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/22")
 5071     (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")
 5072     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/24")
 5073     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/25")
 5074     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/26")
 5075     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/27")
 5076     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/28")
 5077     (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")
 5078     (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")
 5079     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/31")
 5080     # . epilogue
 5081     89/<- %esp 5/r32/ebp
 5082     5d/pop-to-ebp
 5083     c3/return
 5084 
 5085 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2:
 5086     # . prologue
 5087     55/push-ebp
 5088     89/<- %ebp 4/r32/esp
 5089     # setup
 5090     (clear-stream _test-input-stream)
 5091     (clear-stream $_test-input-buffered-file->buffer)
 5092     (clear-stream _test-output-stream)
 5093     (clear-stream $_test-output-buffered-file->buffer)
 5094     # non-local conditional branch from a block without a local variable,
 5095     # unwinding a local on the stack
 5096     (write _test-input-stream "fn foo {\n")
 5097     (write _test-input-stream "  a: {\n")
 5098     (write _test-input-stream "    var x: int\n")
 5099     (write _test-input-stream "    {\n")
 5100     (write _test-input-stream "      break-if->= a\n")
 5101     (write _test-input-stream "    }\n")
 5102     (write _test-input-stream "  }\n")
 5103     (write _test-input-stream "}\n")
 5104     # convert
 5105     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5106     (flush _test-output-buffered-file)
 5107 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5113     # check output
 5114     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/0")
 5115     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/1")
 5116     (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")
 5117     (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")
 5118     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/4")
 5119     (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")
 5120     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/6")
 5121     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/7")
 5122     (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")
 5123     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/9")
 5124     (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")
 5125     (check-next-stream-line-equal _test-output-stream "        {"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/11")
 5126     (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")
 5127     (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")
 5128     (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")
 5129     (check-next-stream-line-equal _test-output-stream "        }"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/15")
 5130     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/16")
 5131     (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")
 5132     (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")
 5133     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/19")
 5134     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/20")
 5135     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/21")
 5136     (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")
 5137     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/23")
 5138     (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")
 5139     (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")
 5140     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/26")
 5141     # . epilogue
 5142     89/<- %esp 5/r32/ebp
 5143     5d/pop-to-ebp
 5144     c3/return
 5145 
 5146 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3:
 5147     # . prologue
 5148     55/push-ebp
 5149     89/<- %ebp 4/r32/esp
 5150     # setup
 5151     (clear-stream _test-input-stream)
 5152     (clear-stream $_test-input-buffered-file->buffer)
 5153     (clear-stream _test-output-stream)
 5154     (clear-stream $_test-output-buffered-file->buffer)
 5155     # non-local unconditional branch from a block without a local variable,
 5156     # unwinding a local on the stack
 5157     (write _test-input-stream "fn foo {\n")
 5158     (write _test-input-stream "  a: {\n")
 5159     (write _test-input-stream "    var x: int\n")
 5160     (write _test-input-stream "    {\n")
 5161     (write _test-input-stream "      break a\n")
 5162     (write _test-input-stream "    }\n")
 5163     (write _test-input-stream "  }\n")
 5164     (write _test-input-stream "}\n")
 5165     # convert
 5166     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5167     (flush _test-output-buffered-file)
 5168 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5174     # check output
 5175     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/0")
 5176     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/1")
 5177     (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")
 5178     (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")
 5179     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/4")
 5180     (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")
 5181     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/6")
 5182     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/7")
 5183     (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")
 5184     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/9")
 5185     (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")
 5186     (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")
 5187     (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")
 5188     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/14")
 5189     (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")
 5190     (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")
 5191     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/17")
 5192     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/18")
 5193     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/19")
 5194     (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")
 5195     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/21")
 5196     (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")
 5197     (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")
 5198     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/24")
 5199     # . epilogue
 5200     89/<- %esp 5/r32/ebp
 5201     5d/pop-to-ebp
 5202     c3/return
 5203 
 5204 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4:
 5205     # . prologue
 5206     55/push-ebp
 5207     89/<- %ebp 4/r32/esp
 5208     # setup
 5209     (clear-stream _test-input-stream)
 5210     (clear-stream $_test-input-buffered-file->buffer)
 5211     (clear-stream _test-output-stream)
 5212     (clear-stream $_test-output-buffered-file->buffer)
 5213     #
 5214     (write _test-input-stream "fn foo {\n")
 5215     (write _test-input-stream "  a: {\n")
 5216     (write _test-input-stream "    var x/esi: int <- copy 0\n")
 5217     (write _test-input-stream "    {\n")
 5218     (write _test-input-stream "      break a\n")
 5219     (write _test-input-stream "    }\n")
 5220     (write _test-input-stream "  }\n")
 5221     (write _test-input-stream "}\n")
 5222     # convert
 5223     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5224     (flush _test-output-buffered-file)
 5225 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5231     # check output
 5232     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/0")
 5233     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/1")
 5234     (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")
 5235     (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")
 5236     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/4")
 5237     (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")
 5238     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/6")
 5239     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/7")
 5240     (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")
 5241     (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")
 5242     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/10")
 5243     (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")
 5244     (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")
 5245     (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")
 5246     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/14")
 5247     (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")
 5248     (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")
 5249     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/17")
 5250     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/18")
 5251     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/19")
 5252     (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")
 5253     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/21")
 5254     (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")
 5255     (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")
 5256     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/24")
 5257     # . epilogue
 5258     89/<- %esp 5/r32/ebp
 5259     5d/pop-to-ebp
 5260     c3/return
 5261 
 5262 test-convert-function-with-nonlocal-unconditional-break-and-local-vars:
 5263     # . prologue
 5264     55/push-ebp
 5265     89/<- %ebp 4/r32/esp
 5266     # setup
 5267     (clear-stream _test-input-stream)
 5268     (clear-stream $_test-input-buffered-file->buffer)
 5269     (clear-stream _test-output-stream)
 5270     (clear-stream $_test-output-buffered-file->buffer)
 5271     #
 5272     (write _test-input-stream "fn foo {\n")
 5273     (write _test-input-stream "  a: {\n")
 5274     (write _test-input-stream "    var x: int\n")
 5275     (write _test-input-stream "    {\n")
 5276     (write _test-input-stream "      var y: int\n")
 5277     (write _test-input-stream "      break a\n")
 5278     (write _test-input-stream "      increment x\n")
 5279     (write _test-input-stream "    }\n")
 5280     (write _test-input-stream "  }\n")
 5281     (write _test-input-stream "}\n")
 5282     # convert
 5283     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5284     (flush _test-output-buffered-file)
 5285 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5291     # check output
 5292     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/0")
 5293     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/1")
 5294     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/2")
 5295     (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")
 5296     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/4")
 5297     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/5")
 5298     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/6")
 5299     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/7")
 5300     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/8")
 5301     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/9")
 5302     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/10")
 5303     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/11")
 5304     (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")
 5305     (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")
 5306     (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")
 5307     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/15")
 5308     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/16")
 5309     (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")
 5310     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/18")
 5311     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/19")
 5312     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/20")
 5313     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/21")
 5314     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/22")
 5315     (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")
 5316     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/24")
 5317     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/25")
 5318     # . epilogue
 5319     89/<- %esp 5/r32/ebp
 5320     5d/pop-to-ebp
 5321     c3/return
 5322 
 5323 test-convert-function-with-unconditional-break-and-local-vars:
 5324     # . prologue
 5325     55/push-ebp
 5326     89/<- %ebp 4/r32/esp
 5327     # setup
 5328     (clear-stream _test-input-stream)
 5329     (clear-stream $_test-input-buffered-file->buffer)
 5330     (clear-stream _test-output-stream)
 5331     (clear-stream $_test-output-buffered-file->buffer)
 5332     #
 5333     (write _test-input-stream "fn foo {\n")
 5334     (write _test-input-stream "  {\n")
 5335     (write _test-input-stream "    var x: int\n")
 5336     (write _test-input-stream "    {\n")
 5337     (write _test-input-stream "      var y: int\n")
 5338     (write _test-input-stream "      break\n")
 5339     (write _test-input-stream "      increment x\n")
 5340     (write _test-input-stream "    }\n")
 5341     (write _test-input-stream "  }\n")
 5342     (write _test-input-stream "}\n")
 5343     # convert
 5344     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5345     (flush _test-output-buffered-file)
 5346 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5352     # check output
 5353     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-unconditional-break-and-local-vars/0")
 5354     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-unconditional-break-and-local-vars/1")
 5355     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-unconditional-break-and-local-vars/2")
 5356     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-unconditional-break-and-local-vars/3")
 5357     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-unconditional-break-and-local-vars/4")
 5358     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-unconditional-break-and-local-vars/5")
 5359     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-unconditional-break-and-local-vars/6")
 5360     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-unconditional-break-and-local-vars/7")
 5361     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-unconditional-break-and-local-vars/8")
 5362     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-unconditional-break-and-local-vars/9")
 5363     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-unconditional-break-and-local-vars/10")
 5364     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-unconditional-break-and-local-vars/11")
 5365     (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")
 5366     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-unconditional-break-and-local-vars/13")
 5367     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-unconditional-break-and-local-vars/14")
 5368     (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")
 5369     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-unconditional-break-and-local-vars/16")
 5370     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-unconditional-break-and-local-vars/17")
 5371     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-unconditional-break-and-local-vars/18")
 5372     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-unconditional-break-and-local-vars/19")
 5373     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-unconditional-break-and-local-vars/20")
 5374     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-unconditional-break-and-local-vars/21")
 5375     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-unconditional-break-and-local-vars/22")
 5376     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-unconditional-break-and-local-vars/23")
 5377     # . epilogue
 5378     89/<- %esp 5/r32/ebp
 5379     5d/pop-to-ebp
 5380     c3/return
 5381 
 5382 test-convert-function-with-nonlocal-unconditional-loop-and-local-vars:
 5383     # . prologue
 5384     55/push-ebp
 5385     89/<- %ebp 4/r32/esp
 5386     # setup
 5387     (clear-stream _test-input-stream)
 5388     (clear-stream $_test-input-buffered-file->buffer)
 5389     (clear-stream _test-output-stream)
 5390     (clear-stream $_test-output-buffered-file->buffer)
 5391     #
 5392     (write _test-input-stream "fn foo {\n")
 5393     (write _test-input-stream "  a: {\n")
 5394     (write _test-input-stream "    var x: int\n")
 5395     (write _test-input-stream "    {\n")
 5396     (write _test-input-stream "      var y: int\n")
 5397     (write _test-input-stream "      loop a\n")
 5398     (write _test-input-stream "      increment x\n")
 5399     (write _test-input-stream "    }\n")
 5400     (write _test-input-stream "  }\n")
 5401     (write _test-input-stream "}\n")
 5402     # convert
 5403     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5404     (flush _test-output-buffered-file)
 5405 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5411     # check output
 5412     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/0")
 5413     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/1")
 5414     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/2")
 5415     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/3")
 5416     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/4")
 5417     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/5")
 5418     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/6")
 5419     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/7")
 5420     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/8")
 5421     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/9")
 5422     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/10")
 5423     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/11")
 5424     (check-next-stream-line-equal _test-output-stream "        81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/12")
 5425     (check-next-stream-line-equal _test-output-stream "        81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/13")
 5426     (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")
 5427     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/15")
 5428     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/16")
 5429     (check-next-stream-line-equal _test-output-stream "      81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/17")
 5430     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/18")
 5431     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/19")
 5432     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/20")
 5433     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/21")
 5434     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/22")
 5435     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/23")
 5436     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/24")
 5437     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/25")
 5438     # . epilogue
 5439     89/<- %esp 5/r32/ebp
 5440     5d/pop-to-ebp
 5441     c3/return
 5442 
 5443 test-convert-function-with-local-array-var-in-mem:
 5444     # . prologue
 5445     55/push-ebp
 5446     89/<- %ebp 4/r32/esp
 5447     # setup
 5448     (clear-stream _test-input-stream)
 5449     (clear-stream $_test-input-buffered-file->buffer)
 5450     (clear-stream _test-output-stream)
 5451     (clear-stream $_test-output-buffered-file->buffer)
 5452     #
 5453     (write _test-input-stream "fn foo {\n")
 5454     (write _test-input-stream "  var x: (array int 3)\n")
 5455     (write _test-input-stream "}\n")
 5456     # convert
 5457     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5458     (flush _test-output-buffered-file)
 5459 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5465     # check output
 5466     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-array-var-in-mem/0")
 5467     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-array-var-in-mem/1")
 5468     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-array-var-in-mem/2")
 5469     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-array-var-in-mem/3")
 5470     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-array-var-in-mem/4")
 5471     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-array-var-in-mem/5")
 5472     # define x
 5473     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x0000000c)"  "F - test-convert-function-with-local-array-var-in-mem/7")
 5474     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"  "F - test-convert-function-with-local-array-var-in-mem/8")
 5475     # reclaim x
 5476     (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")
 5477     #
 5478     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-array-var-in-mem/10")
 5479     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-array-var-in-mem/11")
 5480     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-array-var-in-mem/12")
 5481     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-array-var-in-mem/13")
 5482     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-array-var-in-mem/14")
 5483     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-array-var-in-mem/15")
 5484     # . epilogue
 5485     89/<- %esp 5/r32/ebp
 5486     5d/pop-to-ebp
 5487     c3/return
 5488 
 5489 test-array-size-in-hex:
 5490     # . prologue
 5491     55/push-ebp
 5492     89/<- %ebp 4/r32/esp
 5493     # setup
 5494     (clear-stream _test-input-stream)
 5495     (clear-stream $_test-input-buffered-file->buffer)
 5496     (clear-stream _test-output-stream)
 5497     (clear-stream $_test-output-buffered-file->buffer)
 5498     (clear-stream _test-error-stream)
 5499     (clear-stream $_test-error-buffered-file->buffer)
 5500     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 5501     68/push 0/imm32
 5502     68/push 0/imm32
 5503     89/<- %edx 4/r32/esp
 5504     (tailor-exit-descriptor %edx 0x10)
 5505     #
 5506     (write _test-input-stream "fn foo {\n")
 5507     (write _test-input-stream "  var x: (array int 10)\n")
 5508     (write _test-input-stream "}\n")
 5509     # convert
 5510     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 5511     # registers except esp clobbered at this point
 5512     # restore ed
 5513     89/<- %edx 4/r32/esp
 5514     (flush _test-output-buffered-file)
 5515     (flush _test-error-buffered-file)
 5516 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 5522     # check output
 5523     (check-stream-equal _test-output-stream  ""  "F - test-array-size-in-hex: output should be empty")
 5524     (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")
 5525     # check that stop(1) was called
 5526     (check-ints-equal *(edx+4) 2 "F - test-array-size-in-hex: exit status")
 5527     # don't restore from ebp
 5528     81 0/subop/add %esp 8/imm32
 5529     # . epilogue
 5530     5d/pop-to-ebp
 5531     c3/return
 5532 
 5533 test-convert-function-with-populate:
 5534     # . prologue
 5535     55/push-ebp
 5536     89/<- %ebp 4/r32/esp
 5537     # setup
 5538     (clear-stream _test-input-stream)
 5539     (clear-stream $_test-input-buffered-file->buffer)
 5540     (clear-stream _test-output-stream)
 5541     (clear-stream $_test-output-buffered-file->buffer)
 5542     #
 5543     (write _test-input-stream "fn foo {\n")
 5544     (write _test-input-stream "  var x/ecx: (addr handle array int) <- copy 0\n")
 5545     (write _test-input-stream "  populate x, 7\n")
 5546     (write _test-input-stream "}\n")
 5547     # convert
 5548     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5549     (flush _test-output-buffered-file)
 5550 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5556     # check output
 5557     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-populate/0")
 5558     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-populate/1")
 5559     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-populate/2")
 5560     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-populate/3")
 5561     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-populate/4")
 5562     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-populate/5")
 5563     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-populate/6")
 5564     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-function-with-populate/7")
 5565     (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)
 5566     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-populate/9")
 5567     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-populate/10")
 5568     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-populate/11")
 5569     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-populate/12")
 5570     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-populate/13")
 5571     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-populate/14")
 5572     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-populate/15")
 5573     # . epilogue
 5574     89/<- %esp 5/r32/ebp
 5575     5d/pop-to-ebp
 5576     c3/return
 5577 
 5578 # special-case for size(byte) when allocating array
 5579 test-convert-function-with-local-array-of-bytes-in-mem:
 5580     # . prologue
 5581     55/push-ebp
 5582     89/<- %ebp 4/r32/esp
 5583     # setup
 5584     (clear-stream _test-input-stream)
 5585     (clear-stream $_test-input-buffered-file->buffer)
 5586     (clear-stream _test-output-stream)
 5587     (clear-stream $_test-output-buffered-file->buffer)
 5588     #
 5589     (write _test-input-stream "fn foo {\n")
 5590     (write _test-input-stream "  var x: (array byte 3)\n")
 5591     (write _test-input-stream "}\n")
 5592     # convert
 5593     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5594     (flush _test-output-buffered-file)
 5595 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5601     # check output
 5602     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-array-of-bytes-in-mem/0")
 5603     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-array-of-bytes-in-mem/1")
 5604     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-array-of-bytes-in-mem/2")
 5605     (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")
 5606     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-array-of-bytes-in-mem/4")
 5607     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-array-of-bytes-in-mem/5")
 5608     # define x
 5609     (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")
 5610     (check-next-stream-line-equal _test-output-stream "    68/push 0x00000003/imm32"  "F - test-convert-function-with-local-array-of-bytes-in-mem/8")
 5611     # reclaim x
 5612     (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")
 5613     #
 5614     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-array-of-bytes-in-mem/10")
 5615     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-array-of-bytes-in-mem/11")
 5616     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-array-of-bytes-in-mem/12")
 5617     (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")
 5618     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-array-of-bytes-in-mem/14")
 5619     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-array-of-bytes-in-mem/15")
 5620     # . epilogue
 5621     89/<- %esp 5/r32/ebp
 5622     5d/pop-to-ebp
 5623     c3/return
 5624 
 5625 test-convert-address:
 5626     # . prologue
 5627     55/push-ebp
 5628     89/<- %ebp 4/r32/esp
 5629     # setup
 5630     (clear-stream _test-input-stream)
 5631     (clear-stream $_test-input-buffered-file->buffer)
 5632     (clear-stream _test-output-stream)
 5633     (clear-stream $_test-output-buffered-file->buffer)
 5634     #
 5635     (write _test-input-stream "fn foo {\n")
 5636     (write _test-input-stream "  var a: int\n")
 5637     (write _test-input-stream "  var b/eax: (addr int) <- address a\n")
 5638     (write _test-input-stream "}\n")
 5639     # convert
 5640     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5641     (flush _test-output-buffered-file)
 5642 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5648     # check output
 5649     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-address/0")
 5650     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-address/1")
 5651     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-address/2")
 5652     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-address/3")
 5653     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-address/4")
 5654     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-address/5")
 5655     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-address/6")
 5656     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-address/7")
 5657     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp+0xfffffffc) 0x00000000/r32"  "F - test-convert-address/8")
 5658     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-address/9")
 5659     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-address/10")
 5660     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-address/11")
 5661     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-address/12")
 5662     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-address/13")
 5663     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-address/14")
 5664     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-address/15")
 5665     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-address/16")
 5666     # . epilogue
 5667     89/<- %esp 5/r32/ebp
 5668     5d/pop-to-ebp
 5669     c3/return
 5670 
 5671 test-convert-floating-point-convert:
 5672     # . prologue
 5673     55/push-ebp
 5674     89/<- %ebp 4/r32/esp
 5675     # setup
 5676     (clear-stream _test-input-stream)
 5677     (clear-stream $_test-input-buffered-file->buffer)
 5678     (clear-stream _test-output-stream)
 5679     (clear-stream $_test-output-buffered-file->buffer)
 5680     #
 5681     (write _test-input-stream "fn foo {\n")
 5682     (write _test-input-stream "  var a/eax: int <- copy 0\n")
 5683     (write _test-input-stream "  var b/xmm1: float <- convert a\n")
 5684     (write _test-input-stream "}\n")
 5685     # convert
 5686     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5687     (flush _test-output-buffered-file)
 5688 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5694     # check output
 5695     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-floating-point-convert/0")
 5696     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-floating-point-convert/1")
 5697     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-floating-point-convert/2")
 5698     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-floating-point-convert/3")
 5699     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-floating-point-convert/4")
 5700     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-floating-point-convert/5")
 5701     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-floating-point-convert/6")
 5702     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"  "F - test-convert-floating-point-convert/7")
 5703     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"  "F - test-convert-floating-point-convert/8")
 5704     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 1/x32"  "F - test-convert-floating-point-convert/9")
 5705     (check-next-stream-line-equal _test-output-stream "    f3 0f 2a/convert-to-float %eax 0x00000001/x32"  "F - test-convert-floating-point-convert/10")
 5706     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 1/x32"  "F - test-convert-floating-point-convert/11")
 5707     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-floating-point-convert/12")
 5708     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-floating-point-convert/13")
 5709     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-floating-point-convert/14")
 5710     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-floating-point-convert/15")
 5711     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-floating-point-convert/16")
 5712     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-floating-point-convert/17")
 5713     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-floating-point-convert/18")
 5714     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-floating-point-convert/19")
 5715     # . epilogue
 5716     89/<- %esp 5/r32/ebp
 5717     5d/pop-to-ebp
 5718     c3/return
 5719 
 5720 test-convert-floating-point-convert-2:
 5721     # . prologue
 5722     55/push-ebp
 5723     89/<- %ebp 4/r32/esp
 5724     # setup
 5725     (clear-stream _test-input-stream)
 5726     (clear-stream $_test-input-buffered-file->buffer)
 5727     (clear-stream _test-output-stream)
 5728     (clear-stream $_test-output-buffered-file->buffer)
 5729     #
 5730     (write _test-input-stream "fn foo {\n")
 5731     (write _test-input-stream "  var a/eax: int <- copy 0\n")
 5732     (write _test-input-stream "  var b/xmm1: float <- convert a\n")
 5733     (write _test-input-stream "  a <- convert b\n")
 5734     (write _test-input-stream "}\n")
 5735     # convert
 5736     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5737     (flush _test-output-buffered-file)
 5738 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5744     # check output
 5745     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-floating-point-convert-2/0")
 5746     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-floating-point-convert-2/1")
 5747     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-floating-point-convert-2/2")
 5748     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-floating-point-convert-2/3")
 5749     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-floating-point-convert-2/4")
 5750     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-floating-point-convert-2/5")
 5751     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-floating-point-convert-2/6")
 5752     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"  "F - test-convert-floating-point-convert-2/7")
 5753     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"  "F - test-convert-floating-point-convert-2/8")
 5754     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 1/x32"  "F - test-convert-floating-point-convert-2/9")
 5755     (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")
 5756     (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")
 5757     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 1/x32"  "F - test-convert-floating-point-convert-2/12")
 5758     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-floating-point-convert-2/13")
 5759     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-floating-point-convert-2/14")
 5760     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-floating-point-convert-2/15")
 5761     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-floating-point-convert-2/16")
 5762     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-floating-point-convert-2/17")
 5763     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-floating-point-convert-2/18")
 5764     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-floating-point-convert-2/19")
 5765     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-floating-point-convert-2/20")
 5766     # . epilogue
 5767     89/<- %esp 5/r32/ebp
 5768     5d/pop-to-ebp
 5769     c3/return
 5770 
 5771 test-convert-floating-point-operation:
 5772     # . prologue
 5773     55/push-ebp
 5774     89/<- %ebp 4/r32/esp
 5775     # setup
 5776     (clear-stream _test-input-stream)
 5777     (clear-stream $_test-input-buffered-file->buffer)
 5778     (clear-stream _test-output-stream)
 5779     (clear-stream $_test-output-buffered-file->buffer)
 5780     #
 5781     (write _test-input-stream "fn f {\n")
 5782     (write _test-input-stream "  var m: float\n")
 5783     (write _test-input-stream "  var x/xmm1: float <- copy m\n")
 5784     (write _test-input-stream "  var y/xmm5: float <- copy m\n")
 5785     (write _test-input-stream "  x <- copy y\n")
 5786     (write _test-input-stream "  copy-to m, y\n")
 5787     (write _test-input-stream "  x <- add y\n")
 5788     (write _test-input-stream "  x <- add m\n")
 5789     (write _test-input-stream "  x <- subtract y\n")
 5790     (write _test-input-stream "  x <- subtract m\n")
 5791     (write _test-input-stream "  x <- multiply y\n")
 5792     (write _test-input-stream "  x <- multiply m\n")
 5793     (write _test-input-stream "  x <- divide y\n")
 5794     (write _test-input-stream "  x <- divide m\n")
 5795     (write _test-input-stream "  x <- reciprocal y\n")
 5796     (write _test-input-stream "  x <- reciprocal m\n")
 5797     (write _test-input-stream "  x <- square-root y\n")
 5798     (write _test-input-stream "  x <- square-root m\n")
 5799     (write _test-input-stream "  x <- inverse-square-root y\n")
 5800     (write _test-input-stream "  x <- inverse-square-root m\n")
 5801     (write _test-input-stream "  x <- max y\n")
 5802     (write _test-input-stream "  x <- max m\n")
 5803     (write _test-input-stream "  x <- min y\n")
 5804     (write _test-input-stream "  x <- min m\n")
 5805     (write _test-input-stream "  compare x, y\n")
 5806     (write _test-input-stream "  compare x, m\n")
 5807     (write _test-input-stream "}\n")
 5808     # convert
 5809     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5810     (flush _test-output-buffered-file)
 5811 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5817     # check output
 5818     (check-next-stream-line-equal _test-output-stream "f:"                                                                     "F - test-convert-floating-point-operation/0")
 5819     (check-next-stream-line-equal _test-output-stream "  # . prologue"                                                         "F - test-convert-floating-point-operation/1")
 5820     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                                                          "F - test-convert-floating-point-operation/2")
 5821     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                                                 "F - test-convert-floating-point-operation/3")
 5822     (check-next-stream-line-equal _test-output-stream "  {"                                                                    "F - test-convert-floating-point-operation/4")
 5823     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"                                                    "F - test-convert-floating-point-operation/5")
 5824     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"                                                    "F - test-convert-floating-point-operation/6")
 5825     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"                                   "F - test-convert-floating-point-operation/7")
 5826     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 1/x32"                                             "F - test-convert-floating-point-operation/8")
 5827     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/copy *(ebp+0xfffffffc) 0x00000001/x32"                     "F - test-convert-floating-point-operation/9")
 5828     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"                                   "F - test-convert-floating-point-operation/10")
 5829     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 5/x32"                                             "F - test-convert-floating-point-operation/11")
 5830     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/copy *(ebp+0xfffffffc) 0x00000005/x32"                     "F - test-convert-floating-point-operation/12")
 5831     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/copy %xmm1 0x00000005/x32"                                 "F - test-convert-floating-point-operation/13")
 5832     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/copy *(ebp+0xfffffffc) 0x00000005/x32"                     "F - test-convert-floating-point-operation/14")
 5833     (check-next-stream-line-equal _test-output-stream "    f3 0f 58/add %xmm5 0x00000001/x32"                                  "F - test-convert-floating-point-operation/15")
 5834     (check-next-stream-line-equal _test-output-stream "    f3 0f 58/add *(ebp+0xfffffffc) 0x00000001/x32"                      "F - test-convert-floating-point-operation/16")
 5835     (check-next-stream-line-equal _test-output-stream "    f3 0f 5c/subtract %xmm5 0x00000001/x32"                             "F - test-convert-floating-point-operation/17")
 5836     (check-next-stream-line-equal _test-output-stream "    f3 0f 5c/subtract *(ebp+0xfffffffc) 0x00000001/x32"                 "F - test-convert-floating-point-operation/18")
 5837     (check-next-stream-line-equal _test-output-stream "    f3 0f 59/multiply %xmm5 0x00000001/x32"                             "F - test-convert-floating-point-operation/19")
 5838     (check-next-stream-line-equal _test-output-stream "    f3 0f 59/multiply *(ebp+0xfffffffc) 0x00000001/x32"                 "F - test-convert-floating-point-operation/20")
 5839     (check-next-stream-line-equal _test-output-stream "    f3 0f 5e/divide %xmm5 0x00000001/x32"                               "F - test-convert-floating-point-operation/21")
 5840     (check-next-stream-line-equal _test-output-stream "    f3 0f 5e/divide *(ebp+0xfffffffc) 0x00000001/x32"                   "F - test-convert-floating-point-operation/22")
 5841     (check-next-stream-line-equal _test-output-stream "    f3 0f 53/reciprocal %xmm5 0x00000001/x32"                           "F - test-convert-floating-point-operation/23")
 5842     (check-next-stream-line-equal _test-output-stream "    f3 0f 53/reciprocal *(ebp+0xfffffffc) 0x00000001/x32"               "F - test-convert-floating-point-operation/24")
 5843     (check-next-stream-line-equal _test-output-stream "    f3 0f 51/square-root %xmm5 0x00000001/x32"                          "F - test-convert-floating-point-operation/25")
 5844     (check-next-stream-line-equal _test-output-stream "    f3 0f 51/square-root *(ebp+0xfffffffc) 0x00000001/x32"              "F - test-convert-floating-point-operation/26")
 5845     (check-next-stream-line-equal _test-output-stream "    f3 0f 52/inverse-square-root %xmm5 0x00000001/x32"                  "F - test-convert-floating-point-operation/27")
 5846     (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")
 5847     (check-next-stream-line-equal _test-output-stream "    f3 0f 5f/max %xmm5 0x00000001/x32"                                  "F - test-convert-floating-point-operation/29")
 5848     (check-next-stream-line-equal _test-output-stream "    f3 0f 5f/max *(ebp+0xfffffffc) 0x00000001/x32"                      "F - test-convert-floating-point-operation/30")
 5849     (check-next-stream-line-equal _test-output-stream "    f3 0f 5d/min %xmm5 0x00000001/x32"                                  "F - test-convert-floating-point-operation/31")
 5850     (check-next-stream-line-equal _test-output-stream "    f3 0f 5d/min *(ebp+0xfffffffc) 0x00000001/x32"                      "F - test-convert-floating-point-operation/32")
 5851     (check-next-stream-line-equal _test-output-stream "    0f 2f/compare %xmm1 0x00000005/x32"                                 "F - test-convert-floating-point-operation/33")
 5852     (check-next-stream-line-equal _test-output-stream "    0f 2f/compare *(ebp+0xfffffffc) 0x00000001/x32"                     "F - test-convert-floating-point-operation/34")
 5853     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 5/x32"                                             "F - test-convert-floating-point-operation/35")
 5854     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"                                        "F - test-convert-floating-point-operation/36")
 5855     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 1/x32"                                             "F - test-convert-floating-point-operation/37")
 5856     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"                                        "F - test-convert-floating-point-operation/38")
 5857     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"                               "F - test-convert-floating-point-operation/39")
 5858     (check-next-stream-line-equal _test-output-stream "  }"                                                                    "F - test-convert-floating-point-operation/40")
 5859     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"                                                   "F - test-convert-floating-point-operation/41")
 5860     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                                                         "F - test-convert-floating-point-operation/42")
 5861     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                                                 "F - test-convert-floating-point-operation/43")
 5862     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                                                        "F - test-convert-floating-point-operation/44")
 5863     (check-next-stream-line-equal _test-output-stream "  c3/return"                                                            "F - test-convert-floating-point-operation/45")
 5864     # . epilogue
 5865     89/<- %esp 5/r32/ebp
 5866     5d/pop-to-ebp
 5867     c3/return
 5868 
 5869 test-convert-floating-point-dereferenced:
 5870     # . prologue
 5871     55/push-ebp
 5872     89/<- %ebp 4/r32/esp
 5873     # setup
 5874     (clear-stream _test-input-stream)
 5875     (clear-stream $_test-input-buffered-file->buffer)
 5876     (clear-stream _test-output-stream)
 5877     (clear-stream $_test-output-buffered-file->buffer)
 5878     #
 5879     (write _test-input-stream "fn f {\n")
 5880     (write _test-input-stream "  var m: float\n")
 5881     (write _test-input-stream "  var x/xmm1: float <- copy m\n")
 5882     (write _test-input-stream "  var y/eax: (addr float) <- copy 0\n")
 5883     (write _test-input-stream "  x <- multiply *y\n")
 5884     (write _test-input-stream "}\n")
 5885     # convert
 5886     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5887     (flush _test-output-buffered-file)
 5888 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5894     # check output
 5895     (check-next-stream-line-equal _test-output-stream "f:"                                                                     "F - test-convert-floating-point-dereferenced/0")
 5896     (check-next-stream-line-equal _test-output-stream "  # . prologue"                                                         "F - test-convert-floating-point-dereferenced/1")
 5897     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                                                          "F - test-convert-floating-point-dereferenced/2")
 5898     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                                                 "F - test-convert-floating-point-dereferenced/3")
 5899     (check-next-stream-line-equal _test-output-stream "  {"                                                                    "F - test-convert-floating-point-dereferenced/4")
 5900     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"                                                    "F - test-convert-floating-point-dereferenced/5")
 5901     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"                                                    "F - test-convert-floating-point-dereferenced/6")
 5902     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"                                   "F - test-convert-floating-point-dereferenced/7")
 5903     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 1/x32"                                             "F - test-convert-floating-point-dereferenced/8")
 5904     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/copy *(ebp+0xfffffffc) 0x00000001/x32"                     "F - test-convert-floating-point-dereferenced/9")
 5905     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                                               "F - test-convert-floating-point-dereferenced/10")
 5906     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                                             "F - test-convert-floating-point-dereferenced/11")
 5907     (check-next-stream-line-equal _test-output-stream "    f3 0f 59/multiply *eax 0x00000001/x32"                              "F - test-convert-floating-point-dereferenced/12")
 5908     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                                                "F - test-convert-floating-point-dereferenced/13")
 5909     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 1/x32"                                             "F - test-convert-floating-point-dereferenced/14")
 5910     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"                                        "F - test-convert-floating-point-dereferenced/15")
 5911     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"                               "F - test-convert-floating-point-dereferenced/16")
 5912     (check-next-stream-line-equal _test-output-stream "  }"                                                                    "F - test-convert-floating-point-dereferenced/17")
 5913     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"                                                   "F - test-convert-floating-point-dereferenced/18")
 5914     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                                                         "F - test-convert-floating-point-dereferenced/19")
 5915     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                                                 "F - test-convert-floating-point-dereferenced/20")
 5916     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                                                        "F - test-convert-floating-point-dereferenced/21")
 5917     (check-next-stream-line-equal _test-output-stream "  c3/return"                                                            "F - test-convert-floating-point-dereferenced/22")
 5918     # . epilogue
 5919     89/<- %esp 5/r32/ebp
 5920     5d/pop-to-ebp
 5921     c3/return
 5922 
 5923 test-convert-length-of-array:
 5924     # . prologue
 5925     55/push-ebp
 5926     89/<- %ebp 4/r32/esp
 5927     # setup
 5928     (clear-stream _test-input-stream)
 5929     (clear-stream $_test-input-buffered-file->buffer)
 5930     (clear-stream _test-output-stream)
 5931     (clear-stream $_test-output-buffered-file->buffer)
 5932     #
 5933     (write _test-input-stream "fn foo a: (addr array int) {\n")
 5934     (write _test-input-stream "  var b/eax: (addr array int) <- copy a\n")
 5935     (write _test-input-stream "  var c/eax: int <- length b\n")
 5936     (write _test-input-stream "}\n")
 5937     # convert
 5938     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5939     (flush _test-output-buffered-file)
 5940 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5946     # check output
 5947     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array/0")
 5948     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array/1")
 5949     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array/2")
 5950     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array/3")
 5951     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array/4")
 5952     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array/5")
 5953     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array/6")
 5954     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-length-of-array/7")
 5955     (check-next-stream-line-equal _test-output-stream "    8b/-> *eax 0x00000000/r32"  "F - test-convert-length-of-array/8")
 5956     (check-next-stream-line-equal _test-output-stream "    c1/shift 5/subop/>> %eax 0x00000002/imm8"  "F - test-convert-length-of-array/9")
 5957     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array/10")
 5958     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array/11")
 5959     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array/12")
 5960     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array/13")
 5961     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array/14")
 5962     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array/15")
 5963     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array/16")
 5964     # . epilogue
 5965     89/<- %esp 5/r32/ebp
 5966     5d/pop-to-ebp
 5967     c3/return
 5968 
 5969 # special-case for size(byte) when computing array length
 5970 test-convert-length-of-array-of-bytes:
 5971     # . prologue
 5972     55/push-ebp
 5973     89/<- %ebp 4/r32/esp
 5974     # setup
 5975     (clear-stream _test-input-stream)
 5976     (clear-stream $_test-input-buffered-file->buffer)
 5977     (clear-stream _test-output-stream)
 5978     (clear-stream $_test-output-buffered-file->buffer)
 5979     #
 5980     (write _test-input-stream "fn foo a: (addr array byte) {\n")
 5981     (write _test-input-stream "  var b/eax: (addr array byte) <- copy a\n")
 5982     (write _test-input-stream "  var c/eax: int <- length b\n")
 5983     (write _test-input-stream "}\n")
 5984     # convert
 5985     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5986     (flush _test-output-buffered-file)
 5987 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5993     # check output
 5994     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-bytes/0")
 5995     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-bytes/1")
 5996     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-bytes/2")
 5997     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array-of-bytes/3")
 5998     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-bytes/4")
 5999     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-bytes/5")
 6000     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array-of-bytes/6")
 6001     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-length-of-array-of-bytes/7")
 6002     (check-next-stream-line-equal _test-output-stream "    8b/-> *eax 0x00000000/r32"  "F - test-convert-length-of-array-of-bytes/8")
 6003     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array-of-bytes/9")
 6004     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-bytes/10")
 6005     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-bytes/11")
 6006     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-bytes/12")
 6007     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array-of-bytes/13")
 6008     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array-of-bytes/14")
 6009     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-bytes/15")
 6010     # . epilogue
 6011     89/<- %esp 5/r32/ebp
 6012     5d/pop-to-ebp
 6013     c3/return
 6014 
 6015 test-convert-length-of-array-on-stack:
 6016     # . prologue
 6017     55/push-ebp
 6018     89/<- %ebp 4/r32/esp
 6019     # setup
 6020     (clear-stream _test-input-stream)
 6021     (clear-stream $_test-input-buffered-file->buffer)
 6022     (clear-stream _test-output-stream)
 6023     (clear-stream $_test-output-buffered-file->buffer)
 6024     #
 6025     (write _test-input-stream "fn foo {\n")
 6026     (write _test-input-stream "  var a: (array int 3)\n")
 6027     (write _test-input-stream "  var b/eax: int <- length a\n")
 6028     (write _test-input-stream "}\n")
 6029     # convert
 6030     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6031     (flush _test-output-buffered-file)
 6032 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6038     # check output
 6039     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-on-stack/0")
 6040     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-on-stack/1")
 6041     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-on-stack/2")
 6042     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array-on-stack/3")
 6043     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-on-stack/4")
 6044     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-on-stack/5")
 6045     # define x
 6046     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x0000000c)"  "F - test-convert-length-of-array-on-stack/6")
 6047     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"  "F - test-convert-length-of-array-on-stack/7")
 6048     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array-on-stack/8")
 6049     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0xfffffff0) 0x00000000/r32"  "F - test-convert-length-of-array-on-stack/9")
 6050     (check-next-stream-line-equal _test-output-stream "    c1/shift 5/subop/>> %eax 0x00000002/imm8"  "F - test-convert-length-of-array-on-stack/10")
 6051     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array-on-stack/11")
 6052     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000010/imm32"  "F - test-convert-length-of-array-on-stack/12")
 6053     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-on-stack/13")
 6054     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-on-stack/14")
 6055     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-on-stack/15")
 6056     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array-on-stack/16")
 6057     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array-on-stack/17")
 6058     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-on-stack/18")
 6059     # . epilogue
 6060     89/<- %esp 5/r32/ebp
 6061     5d/pop-to-ebp
 6062     c3/return
 6063 
 6064 test-reg-var-def-with-read-of-same-register:
 6065     # . prologue
 6066     55/push-ebp
 6067     89/<- %ebp 4/r32/esp
 6068     # setup
 6069     (clear-stream _test-input-stream)
 6070     (clear-stream $_test-input-buffered-file->buffer)
 6071     (clear-stream _test-output-stream)
 6072     (clear-stream $_test-output-buffered-file->buffer)
 6073     (clear-stream _test-error-stream)
 6074     (clear-stream $_test-error-buffered-file->buffer)
 6075     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)  # bytes of args in call to convert-mu
 6076     68/push 0/imm32
 6077     68/push 0/imm32
 6078     89/<- %edx 4/r32/esp
 6079     (tailor-exit-descriptor %edx 0x10)
 6080     #
 6081     (write _test-input-stream "fn foo {\n")
 6082     (write _test-input-stream "  var x/eax: int <- copy 3\n")
 6083     (write _test-input-stream "  var y/eax: int <- add x\n")
 6084     (write _test-input-stream "}\n")
 6085     # convert
 6086     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6087     # registers except esp could be clobbered at this point (though they shouldn't be)
 6088     # restore ed
 6089     89/<- %edx 4/r32/esp
 6090     (flush _test-output-buffered-file)
 6091     (flush _test-error-buffered-file)
 6092 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6098 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 6104     (check-stream-equal _test-error-stream  ""  "F - test-reg-var-def-with-read-of-same-register: error stream should be empty")
 6105     # check output
 6106     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-reg-var-def-with-read-of-same-register/0")
 6107     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-reg-var-def-with-read-of-same-register/1")
 6108     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-reg-var-def-with-read-of-same-register/2")
 6109     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-reg-var-def-with-read-of-same-register/3")
 6110     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-reg-var-def-with-read-of-same-register/4")
 6111     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-reg-var-def-with-read-of-same-register/5")
 6112     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-reg-var-def-with-read-of-same-register/6")
 6113     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 3/imm32"                  "F - test-reg-var-def-with-read-of-same-register/7")
 6114     (check-next-stream-line-equal _test-output-stream "    01/add-to %eax 0x00000000/r32"           "F - test-reg-var-def-with-read-of-same-register/8")
 6115     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-reg-var-def-with-read-of-same-register/9")
 6116     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-reg-var-def-with-read-of-same-register/10")
 6117     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-reg-var-def-with-read-of-same-register/11")
 6118     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-reg-var-def-with-read-of-same-register/12")
 6119     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-reg-var-def-with-read-of-same-register/13")
 6120     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-reg-var-def-with-read-of-same-register/14")
 6121     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-reg-var-def-with-read-of-same-register/15")
 6122     # don't restore from ebp
 6123     81 0/subop/add %esp 8/imm32
 6124     # . epilogue
 6125     5d/pop-to-ebp
 6126     c3/return
 6127 
 6128 test-convert-index-into-array:
 6129     # . prologue
 6130     55/push-ebp
 6131     89/<- %ebp 4/r32/esp
 6132     # setup
 6133     (clear-stream _test-input-stream)
 6134     (clear-stream $_test-input-buffered-file->buffer)
 6135     (clear-stream _test-output-stream)
 6136     (clear-stream $_test-output-buffered-file->buffer)
 6137     #
 6138     (write _test-input-stream "fn foo {\n")
 6139     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
 6140     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
 6141     (write _test-input-stream "  var x/eax: (addr int) <- index arr, idx\n")
 6142     (write _test-input-stream "}\n")
 6143     # convert
 6144     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6145     (flush _test-output-buffered-file)
 6146 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6152     # check output
 6153     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array/0")
 6154     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array/1")
 6155     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array/2")
 6156     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array/3")
 6157     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array/4")
 6158     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array/5")
 6159     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array/6")
 6160     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array/7")
 6161     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array/8")
 6162     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-index-into-array/9")
 6163     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds %ecx 0x00000004 *eax \"foo\" \"arr\")"  "F - test-convert-index-into-array/10")
 6164     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx<<0x00000002 + 4) 0x00000000/r32"  "F - test-convert-index-into-array/11")
 6165     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array/12")
 6166     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array/13")
 6167     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array/14")
 6168     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array/15")
 6169     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array/16")
 6170     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array/17")
 6171     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array/18")
 6172     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array/19")
 6173     # . epilogue
 6174     89/<- %esp 5/r32/ebp
 6175     5d/pop-to-ebp
 6176     c3/return
 6177 
 6178 test-convert-index-into-array-of-bytes:
 6179     # . prologue
 6180     55/push-ebp
 6181     89/<- %ebp 4/r32/esp
 6182     # setup
 6183     (clear-stream _test-input-stream)
 6184     (clear-stream $_test-input-buffered-file->buffer)
 6185     (clear-stream _test-output-stream)
 6186     (clear-stream $_test-output-buffered-file->buffer)
 6187     #
 6188     (write _test-input-stream "fn foo {\n")
 6189     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
 6190     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
 6191     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, idx\n")
 6192     (write _test-input-stream "}\n")
 6193     # convert
 6194     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6195     (flush _test-output-buffered-file)
 6196 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6202     # check output
 6203     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes/0")
 6204     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes/1")
 6205     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes/2")
 6206     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-of-bytes/3")
 6207     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes/4")
 6208     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes/5")
 6209     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-of-bytes/6")
 6210     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array-of-bytes/7")
 6211     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-of-bytes/8")
 6212     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-index-into-array-of-bytes/9")
 6213     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds %ecx 0x00000001 *eax \"foo\" \"arr\")"  "F - test-convert-index-into-array-of-bytes/10")
 6214     (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")
 6215     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-of-bytes/12")
 6216     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes/13")
 6217     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes/14")
 6218     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes/15")
 6219     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes/16")
 6220     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes/17")
 6221     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes/18")
 6222     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes/19")
 6223     # . epilogue
 6224     89/<- %esp 5/r32/ebp
 6225     5d/pop-to-ebp
 6226     c3/return
 6227 
 6228 test-convert-index-into-array-with-literal:
 6229     # . prologue
 6230     55/push-ebp
 6231     89/<- %ebp 4/r32/esp
 6232     # setup
 6233     (clear-stream _test-input-stream)
 6234     (clear-stream $_test-input-buffered-file->buffer)
 6235     (clear-stream _test-output-stream)
 6236     (clear-stream $_test-output-buffered-file->buffer)
 6237     #
 6238     (write _test-input-stream "fn foo {\n")
 6239     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
 6240     (write _test-input-stream "  var x/eax: (addr int) <- index arr, 2\n")
 6241     (write _test-input-stream "}\n")
 6242     # convert
 6243     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6244     (flush _test-output-buffered-file)
 6245 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6251     # check output
 6252     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-with-literal/0")
 6253     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-with-literal/1")
 6254     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-with-literal/2")
 6255     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-with-literal/3")
 6256     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-with-literal/4")
 6257     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-with-literal/5")
 6258     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-with-literal/6")
 6259     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array-with-literal/7")
 6260     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds 2 0x00000004 *eax \"foo\" \"arr\")"  "F - test-convert-index-into-array-with-literal/8")
 6261                                                                                  # 2 * 4 bytes/elem + 4 bytes for size = offset 12
 6262     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + 0x0000000c) 0x00000000/r32"  "F - test-convert-index-into-array-with-literal/9")
 6263     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-with-literal/10")
 6264     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-with-literal/11")
 6265     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-with-literal/12")
 6266     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-with-literal/13")
 6267     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-with-literal/14")
 6268     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-with-literal/15")
 6269     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-with-literal/16")
 6270     # . epilogue
 6271     89/<- %esp 5/r32/ebp
 6272     5d/pop-to-ebp
 6273     c3/return
 6274 
 6275 test-convert-index-into-array-of-bytes-with-literal:
 6276     # . prologue
 6277     55/push-ebp
 6278     89/<- %ebp 4/r32/esp
 6279     # setup
 6280     (clear-stream _test-input-stream)
 6281     (clear-stream $_test-input-buffered-file->buffer)
 6282     (clear-stream _test-output-stream)
 6283     (clear-stream $_test-output-buffered-file->buffer)
 6284     #
 6285     (write _test-input-stream "fn foo {\n")
 6286     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
 6287     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, 2\n")
 6288     (write _test-input-stream "}\n")
 6289     # convert
 6290     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6291     (flush _test-output-buffered-file)
 6292 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6298     # check output
 6299     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-with-literal/0")
 6300     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-with-literal/1")
 6301     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-with-literal/2")
 6302     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-of-bytes-with-literal/3")
 6303     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-with-literal/4")
 6304     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-with-literal/5")
 6305     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-of-bytes-with-literal/6")
 6306     (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")
 6307     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds 2 0x00000001 *eax \"foo\" \"arr\")"  "F - test-convert-index-into-array-of-bytes-with-literal/8")
 6308                                                                                  # 2 * 1 byte/elem + 4 bytes for size = offset 6
 6309     (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")
 6310     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes-with-literal/9")
 6311     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-with-literal/10")
 6312     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-with-literal/11")
 6313     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-with-literal/12")
 6314     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes-with-literal/13")
 6315     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes-with-literal/14")
 6316     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-with-literal/15")
 6317     # . epilogue
 6318     89/<- %esp 5/r32/ebp
 6319     5d/pop-to-ebp
 6320     c3/return
 6321 
 6322 test-convert-index-into-array-on-stack:
 6323     # . prologue
 6324     55/push-ebp
 6325     89/<- %ebp 4/r32/esp
 6326     # setup
 6327     (clear-stream _test-input-stream)
 6328     (clear-stream $_test-input-buffered-file->buffer)
 6329     (clear-stream _test-output-stream)
 6330     (clear-stream $_test-output-buffered-file->buffer)
 6331     #
 6332     (write _test-input-stream "fn foo {\n")
 6333     (write _test-input-stream "  var arr: (array int 3)\n")
 6334     (write _test-input-stream "  var idx/eax: int <- copy 2\n")
 6335     (write _test-input-stream "  var x/eax: (addr int) <- index arr, idx\n")
 6336     (write _test-input-stream "}\n")
 6337     # convert
 6338     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6339     (flush _test-output-buffered-file)
 6340 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6346     # check output
 6347     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-on-stack/0")
 6348     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-on-stack/1")
 6349     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-on-stack/2")
 6350     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-on-stack/3")
 6351     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-on-stack/4")
 6352     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-on-stack/5")
 6353     # var arr
 6354     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x0000000c)"          "F - test-convert-index-into-array-on-stack/6")
 6355     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"                "F - test-convert-index-into-array-on-stack/7")
 6356     # var idx
 6357     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-on-stack/8")
 6358     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 2/imm32"                  "F - test-convert-index-into-array-on-stack/9")
 6359     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds %eax 0x00000004 *(ebp+0xfffffff0) \"foo\" \"arr\")"  "F - test-convert-index-into-array-on-stack/10")
 6360     # var x is at (ebp-0x10) + idx<<2 + 4 = ebp + idx<<2 - 0xc
 6361     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp + eax<<0x00000002 + 0xfffffff4) 0x00000000/r32"  "F - test-convert-index-into-array-on-stack/11")
 6362     # reclaim idx
 6363     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-on-stack/12")
 6364     # reclaim arr
 6365     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000010/imm32"    "F - test-convert-index-into-array-on-stack/13")
 6366     #
 6367     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-on-stack/14")
 6368     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-on-stack/15")
 6369     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-on-stack/16")
 6370     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-on-stack/17")
 6371     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-on-stack/18")
 6372     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-on-stack/19")
 6373     # . epilogue
 6374     89/<- %esp 5/r32/ebp
 6375     5d/pop-to-ebp
 6376     c3/return
 6377 
 6378 test-convert-index-into-array-on-stack-with-literal:
 6379     # . prologue
 6380     55/push-ebp
 6381     89/<- %ebp 4/r32/esp
 6382     # setup
 6383     (clear-stream _test-input-stream)
 6384     (clear-stream $_test-input-buffered-file->buffer)
 6385     (clear-stream _test-output-stream)
 6386     (clear-stream $_test-output-buffered-file->buffer)
 6387     #
 6388     (write _test-input-stream "fn foo {\n")
 6389     (write _test-input-stream "  var arr: (array int 3)\n")
 6390     (write _test-input-stream "  var x/eax: (addr int) <- index arr, 2\n")
 6391     (write _test-input-stream "}\n")
 6392     # convert
 6393     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6394     (flush _test-output-buffered-file)
 6395 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6401     # check output
 6402     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-on-stack-with-literal/0")
 6403     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-on-stack-with-literal/1")
 6404     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-on-stack-with-literal/2")
 6405     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-on-stack-with-literal/3")
 6406     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-on-stack-with-literal/4")
 6407     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-on-stack-with-literal/5")
 6408     # var arr
 6409     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x0000000c)"          "F - test-convert-index-into-array-on-stack-with-literal/6")
 6410     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"                "F - test-convert-index-into-array-on-stack-with-literal/7")
 6411     # var x
 6412     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-on-stack-with-literal/8")
 6413     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds 2 0x00000004 *(ebp+0xfffffff0) \"foo\" \"arr\")"  "F - test-convert-index-into-array-on-stack-with-literal/9")
 6414     # x is at (ebp-0x10) + 4 + 2*4 = ebp-4
 6415     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp + 0xfffffffc) 0x00000000/r32"  "F - test-convert-index-into-array-on-stack-with-literal/10")
 6416     # reclaim x
 6417     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-on-stack-with-literal/11")
 6418     # reclaim arr
 6419     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000010/imm32"    "F - test-convert-index-into-array-on-stack-with-literal/12")
 6420     #
 6421     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-on-stack-with-literal/13")
 6422     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-on-stack-with-literal/14")
 6423     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-on-stack-with-literal/15")
 6424     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-on-stack-with-literal/16")
 6425     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-on-stack-with-literal/17")
 6426     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-on-stack-with-literal/18")
 6427     # . epilogue
 6428     89/<- %esp 5/r32/ebp
 6429     5d/pop-to-ebp
 6430     c3/return
 6431 
 6432 test-convert-index-into-array-of-bytes-on-stack-with-literal:
 6433     # . prologue
 6434     55/push-ebp
 6435     89/<- %ebp 4/r32/esp
 6436     # setup
 6437     (clear-stream _test-input-stream)
 6438     (clear-stream $_test-input-buffered-file->buffer)
 6439     (clear-stream _test-output-stream)
 6440     (clear-stream $_test-output-buffered-file->buffer)
 6441     #
 6442     (write _test-input-stream "fn foo {\n")
 6443     (write _test-input-stream "  var arr: (array byte 3)\n")
 6444     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, 2\n")
 6445     (write _test-input-stream "}\n")
 6446     # convert
 6447     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6448     (flush _test-output-buffered-file)
 6449 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6455     # check output
 6456     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/0")
 6457     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/1")
 6458     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/2")
 6459     (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")
 6460     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/4")
 6461     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/5")
 6462     # var arr
 6463     (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")
 6464     (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")
 6465     # var x
 6466     (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")
 6467     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds 2 0x00000001 *(ebp+0xfffffff9) \"foo\" \"arr\")"  "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/9")
 6468     # x is at (ebp-7) + 4 + 2 = ebp-1
 6469     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp + 0xffffffff) 0x00000000/r32"  "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/10")
 6470     # reclaim x
 6471     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/11")
 6472     # reclaim arr
 6473     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000007/imm32"    "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/12")
 6474     #
 6475     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/13")
 6476     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/14")
 6477     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/15")
 6478     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/16")
 6479     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/17")
 6480     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/18")
 6481     # . epilogue
 6482     89/<- %esp 5/r32/ebp
 6483     5d/pop-to-ebp
 6484     c3/return
 6485 
 6486 test-convert-index-into-array-using-offset:
 6487     # . prologue
 6488     55/push-ebp
 6489     89/<- %ebp 4/r32/esp
 6490     # setup
 6491     (clear-stream _test-input-stream)
 6492     (clear-stream $_test-input-buffered-file->buffer)
 6493     (clear-stream _test-output-stream)
 6494     (clear-stream $_test-output-buffered-file->buffer)
 6495     #
 6496     (write _test-input-stream "fn foo {\n")
 6497     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
 6498     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
 6499     (write _test-input-stream "  var off/ecx: (offset int) <- compute-offset arr, idx\n")
 6500     (write _test-input-stream "  var x/eax: (addr int) <- index arr, off\n")
 6501     (write _test-input-stream "}\n")
 6502     # convert
 6503     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6504     (flush _test-output-buffered-file)
 6505 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6511     # check output
 6512     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-using-offset/0")
 6513     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-using-offset/1")
 6514     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-using-offset/2")
 6515     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-using-offset/3")
 6516     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-using-offset/4")
 6517     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-using-offset/5")
 6518     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-using-offset/6")
 6519     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array-using-offset/7")
 6520     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-using-offset/8")
 6521     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-index-into-array-using-offset/9")
 6522     (check-next-stream-line-equal _test-output-stream "    69/multiply %ecx 0x00000004/imm32 0x00000001/r32"  "F - test-convert-index-into-array-using-offset/10")
 6523     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds %ecx 1 *eax \"foo\" \"arr\")"  "F - test-convert-index-into-array-using-offset/11")
 6524     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx + 4) 0x00000000/r32"  "F - test-convert-index-into-array-using-offset/12")
 6525     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-using-offset/13")
 6526     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-using-offset/14")
 6527     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-using-offset/15")
 6528     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-using-offset/16")
 6529     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-using-offset/17")
 6530     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-using-offset/18")
 6531     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-using-offset/19")
 6532     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-using-offset/20")
 6533     # . epilogue
 6534     89/<- %esp 5/r32/ebp
 6535     5d/pop-to-ebp
 6536     c3/return
 6537 
 6538 test-convert-index-into-array-of-bytes-using-offset:
 6539     # . prologue
 6540     55/push-ebp
 6541     89/<- %ebp 4/r32/esp
 6542     # setup
 6543     (clear-stream _test-input-stream)
 6544     (clear-stream $_test-input-buffered-file->buffer)
 6545     (clear-stream _test-output-stream)
 6546     (clear-stream $_test-output-buffered-file->buffer)
 6547     #
 6548     (write _test-input-stream "fn foo {\n")
 6549     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
 6550     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
 6551     (write _test-input-stream "  var off/ecx: (offset byte) <- compute-offset arr, idx\n")
 6552     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, off\n")
 6553     (write _test-input-stream "}\n")
 6554     # convert
 6555     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6556     (flush _test-output-buffered-file)
 6557 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6563     # check output
 6564     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-using-offset/0")
 6565     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-using-offset/1")
 6566     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-using-offset/2")
 6567     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-of-bytes-using-offset/3")
 6568     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-using-offset/4")
 6569     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-using-offset/5")
 6570     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-of-bytes-using-offset/6")
 6571     (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")
 6572     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-of-bytes-using-offset/8")
 6573     (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")
 6574     (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")
 6575     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds %ecx 1 *eax \"foo\" \"arr\")"  "F - test-convert-index-into-array-of-bytes-using-offset/11")
 6576     (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/12")
 6577     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-of-bytes-using-offset/13")
 6578     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes-using-offset/14")
 6579     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-using-offset/15")
 6580     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-using-offset/16")
 6581     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-using-offset/17")
 6582     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes-using-offset/18")
 6583     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes-using-offset/19")
 6584     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-using-offset/20")
 6585     # . epilogue
 6586     89/<- %esp 5/r32/ebp
 6587     5d/pop-to-ebp
 6588     c3/return
 6589 
 6590 test-convert-index-into-array-using-offset-on-stack:
 6591     # . prologue
 6592     55/push-ebp
 6593     89/<- %ebp 4/r32/esp
 6594     # setup
 6595     (clear-stream _test-input-stream)
 6596     (clear-stream $_test-input-buffered-file->buffer)
 6597     (clear-stream _test-output-stream)
 6598     (clear-stream $_test-output-buffered-file->buffer)
 6599     #
 6600     (write _test-input-stream "fn foo {\n")
 6601     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
 6602     (write _test-input-stream "  var idx: int\n")
 6603     (write _test-input-stream "  var off/ecx: (offset int) <- compute-offset arr, idx\n")
 6604     (write _test-input-stream "  var x/eax: (addr int) <- index arr, off\n")
 6605     (write _test-input-stream "}\n")
 6606     # convert
 6607     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6608     (flush _test-output-buffered-file)
 6609 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6615     # check output
 6616     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-using-offset-on-stack/0")
 6617     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-using-offset-on-stack/1")
 6618     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-using-offset-on-stack/2")
 6619     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-using-offset-on-stack/3")
 6620     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-using-offset-on-stack/4")
 6621     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-using-offset-on-stack/5")
 6622     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-using-offset-on-stack/6")
 6623     (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")
 6624     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"                         "F - test-convert-index-into-array-using-offset-on-stack/8")
 6625     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-using-offset-on-stack/9")
 6626     (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")
 6627     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds %ecx 1 *eax \"foo\" \"arr\")"  "F - test-convert-index-into-array-using-offset-on-stack/11")
 6628     (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/12")
 6629     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-using-offset-on-stack/13")
 6630     (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/14")
 6631     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-using-offset-on-stack/15")
 6632     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-using-offset-on-stack/16")
 6633     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-using-offset-on-stack/17")
 6634     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-using-offset-on-stack/18")
 6635     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-using-offset-on-stack/19")
 6636     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-using-offset-on-stack/20")
 6637     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-using-offset-on-stack/21")
 6638     # . epilogue
 6639     89/<- %esp 5/r32/ebp
 6640     5d/pop-to-ebp
 6641     c3/return
 6642 
 6643 test-convert-index-into-array-of-bytes-using-offset-on-stack:
 6644     # . prologue
 6645     55/push-ebp
 6646     89/<- %ebp 4/r32/esp
 6647     # setup
 6648     (clear-stream _test-input-stream)
 6649     (clear-stream $_test-input-buffered-file->buffer)
 6650     (clear-stream _test-output-stream)
 6651     (clear-stream $_test-output-buffered-file->buffer)
 6652     #
 6653     (write _test-input-stream "fn foo {\n")
 6654     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
 6655     (write _test-input-stream "  var idx: int\n")
 6656     (write _test-input-stream "  var off/ecx: (offset byte) <- compute-offset arr, idx\n")
 6657     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, off\n")
 6658     (write _test-input-stream "}\n")
 6659     # convert
 6660     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6661     (flush _test-output-buffered-file)
 6662 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6668     # check output
 6669     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/0")
 6670     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/1")
 6671     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/2")
 6672     (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")
 6673     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/4")
 6674     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/5")
 6675     (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")
 6676     (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")
 6677     (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")
 6678     (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")
 6679     (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")
 6680     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds %ecx 1 *eax \"foo\" \"arr\")"  "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/11")
 6681     (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/12")
 6682     (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/13")
 6683     (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/14")
 6684     (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/15")
 6685     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/16")
 6686     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/17")
 6687     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/18")
 6688     (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/19")
 6689     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/20")
 6690     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/21")
 6691     # . epilogue
 6692     89/<- %esp 5/r32/ebp
 6693     5d/pop-to-ebp
 6694     c3/return
 6695 
 6696 test-convert-function-and-type-definition:
 6697     # . prologue
 6698     55/push-ebp
 6699     89/<- %ebp 4/r32/esp
 6700     # setup
 6701     (clear-stream _test-input-stream)
 6702     (clear-stream $_test-input-buffered-file->buffer)
 6703     (clear-stream _test-output-stream)
 6704     (clear-stream $_test-output-buffered-file->buffer)
 6705     #
 6706     (write _test-input-stream "fn foo a: (addr t) {\n")
 6707     (write _test-input-stream "  var _a/eax: (addr t) <- copy a\n")
 6708     (write _test-input-stream "  var b/ecx: (addr int) <- get _a, x\n")
 6709     (write _test-input-stream "  var c/ecx: (addr int) <- get _a, y\n")
 6710     (write _test-input-stream "}\n")
 6711     (write _test-input-stream "type t {\n")
 6712     (write _test-input-stream "  x: int\n")
 6713     (write _test-input-stream "  y: int\n")
 6714     (write _test-input-stream "}\n")
 6715     # convert
 6716     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6717     (flush _test-output-buffered-file)
 6718 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6724     # check output
 6725     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-and-type-definition/0")
 6726     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-and-type-definition/1")
 6727     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-and-type-definition/2")
 6728     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-and-type-definition/3")
 6729     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-and-type-definition/4")
 6730     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-and-type-definition/5")
 6731     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-and-type-definition/6")
 6732     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-function-and-type-definition/7")
 6733     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-and-type-definition/8")
 6734     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + 0x00000000) 0x00000001/r32"  "F - test-convert-function-and-type-definition/9")
 6735     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + 0x00000004) 0x00000001/r32"  "F - test-convert-function-and-type-definition/11")
 6736     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-and-type-definition/13")
 6737     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-function-and-type-definition/14")
 6738     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-and-type-definition/15")
 6739     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-and-type-definition/16")
 6740     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-and-type-definition/17")
 6741     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-and-type-definition/18")
 6742     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-and-type-definition/19")
 6743     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-and-type-definition/20")
 6744     # . epilogue
 6745     89/<- %esp 5/r32/ebp
 6746     5d/pop-to-ebp
 6747     c3/return
 6748 
 6749 test-type-definition-with-array:
 6750     # . prologue
 6751     55/push-ebp
 6752     89/<- %ebp 4/r32/esp
 6753     # setup
 6754     (clear-stream _test-input-stream)
 6755     (clear-stream $_test-input-buffered-file->buffer)
 6756     (clear-stream _test-output-stream)
 6757     (clear-stream $_test-output-buffered-file->buffer)
 6758     (clear-stream _test-error-stream)
 6759     (clear-stream $_test-error-buffered-file->buffer)
 6760     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6761     68/push 0/imm32
 6762     68/push 0/imm32
 6763     89/<- %edx 4/r32/esp
 6764     (tailor-exit-descriptor %edx 0x10)
 6765     #
 6766     (write _test-input-stream "type t {\n")
 6767     (write _test-input-stream "  a: (array int 3)\n")
 6768     (write _test-input-stream "}\n")
 6769     # convert
 6770     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6771     # registers except esp clobbered at this point
 6772     # restore ed
 6773     89/<- %edx 4/r32/esp
 6774     (flush _test-output-buffered-file)
 6775     (flush _test-error-buffered-file)
 6776 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 6782     # check output
 6783     (check-stream-equal _test-output-stream  ""  "F - test-type-definition-with-array: output should be empty")
 6784     (check-next-stream-line-equal _test-error-stream  "type t: 'array' elements not allowed for now"  "F - test-type-definition-with-array: error message")
 6785     # check that stop(1) was called
 6786     (check-ints-equal *(edx+4) 2 "F - test-type-definition-with-array: exit status")
 6787     # don't restore from ebp
 6788     81 0/subop/add %esp 8/imm32
 6789     # . epilogue
 6790     5d/pop-to-ebp
 6791     c3/return
 6792 
 6793 test-type-definition-with-addr:
 6794     # . prologue
 6795     55/push-ebp
 6796     89/<- %ebp 4/r32/esp
 6797     # setup
 6798     (clear-stream _test-input-stream)
 6799     (clear-stream $_test-input-buffered-file->buffer)
 6800     (clear-stream _test-output-stream)
 6801     (clear-stream $_test-output-buffered-file->buffer)
 6802     (clear-stream _test-error-stream)
 6803     (clear-stream $_test-error-buffered-file->buffer)
 6804     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6805     68/push 0/imm32
 6806     68/push 0/imm32
 6807     89/<- %edx 4/r32/esp
 6808     (tailor-exit-descriptor %edx 0x10)
 6809     #
 6810     (write _test-input-stream "type t {\n")
 6811     (write _test-input-stream "  a: (addr int)\n")
 6812     (write _test-input-stream "}\n")
 6813     # convert
 6814     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6815     # registers except esp clobbered at this point
 6816     # restore ed
 6817     89/<- %edx 4/r32/esp
 6818     (flush _test-output-buffered-file)
 6819     (flush _test-error-buffered-file)
 6820 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 6826     # check output
 6827     (check-stream-equal _test-output-stream  ""  "F - test-type-definition-with-addr: output should be empty")
 6828     (check-next-stream-line-equal _test-error-stream  "type t: 'addr' elements not allowed"  "F - test-type-definition-with-addr: error message")
 6829     # check that stop(1) was called
 6830     (check-ints-equal *(edx+4) 2 "F - test-type-definition-with-addr: exit status")
 6831     # don't restore from ebp
 6832     81 0/subop/add %esp 8/imm32
 6833     # . epilogue
 6834     5d/pop-to-ebp
 6835     c3/return
 6836 
 6837 test-convert-function-with-local-var-with-user-defined-type:
 6838     # . prologue
 6839     55/push-ebp
 6840     89/<- %ebp 4/r32/esp
 6841     # setup
 6842     (clear-stream _test-input-stream)
 6843     (clear-stream $_test-input-buffered-file->buffer)
 6844     (clear-stream _test-output-stream)
 6845     (clear-stream $_test-output-buffered-file->buffer)
 6846     #
 6847     (write _test-input-stream "fn foo {\n")
 6848     (write _test-input-stream "  var a: t\n")
 6849     (write _test-input-stream "}\n")
 6850     (write _test-input-stream "type t {\n")
 6851     (write _test-input-stream "  x: int\n")
 6852     (write _test-input-stream "  y: int\n")
 6853     (write _test-input-stream "}\n")
 6854     # convert
 6855     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6856     (flush _test-output-buffered-file)
 6857 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6863     # check output
 6864     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-with-user-defined-type/0")
 6865     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-with-user-defined-type/1")
 6866     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-with-user-defined-type/2")
 6867     (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")
 6868     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-with-user-defined-type/4")
 6869     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-with-user-defined-type/5")
 6870     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-with-user-defined-type/6")
 6871     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-with-user-defined-type/7")
 6872     (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")
 6873     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-with-user-defined-type/9")
 6874     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-with-user-defined-type/10")
 6875     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-with-user-defined-type/11")
 6876     (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")
 6877     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-with-user-defined-type/13")
 6878     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-with-user-defined-type/14")
 6879     # . epilogue
 6880     89/<- %esp 5/r32/ebp
 6881     5d/pop-to-ebp
 6882     c3/return
 6883 
 6884 test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type:
 6885     # . prologue
 6886     55/push-ebp
 6887     89/<- %ebp 4/r32/esp
 6888     # setup
 6889     (clear-stream _test-input-stream)
 6890     (clear-stream $_test-input-buffered-file->buffer)
 6891     (clear-stream _test-output-stream)
 6892     (clear-stream $_test-output-buffered-file->buffer)
 6893     #
 6894     (write _test-input-stream "fn foo {\n")
 6895     (write _test-input-stream "  var a: t\n")
 6896     (write _test-input-stream "}\n")
 6897     (write _test-input-stream "type t {\n")
 6898     (write _test-input-stream "  x: s\n")
 6899     (write _test-input-stream "}\n")
 6900     (write _test-input-stream "type s {\n")
 6901     (write _test-input-stream "  z: int\n")
 6902     (write _test-input-stream "}\n")
 6903     # convert
 6904     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6905     (flush _test-output-buffered-file)
 6906 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6912     # check output
 6913     (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")
 6914     (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")
 6915     (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")
 6916     (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")
 6917     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/4")
 6918     (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")
 6919     (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")
 6920     (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")
 6921     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/9")
 6922     (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")
 6923     (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")
 6924     (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")
 6925     (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")
 6926     (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")
 6927     # . epilogue
 6928     89/<- %esp 5/r32/ebp
 6929     5d/pop-to-ebp
 6930     c3/return
 6931 
 6932 test-convert-function-call-with-arg-of-user-defined-type:
 6933     # . prologue
 6934     55/push-ebp
 6935     89/<- %ebp 4/r32/esp
 6936     # setup
 6937     (clear-stream _test-input-stream)
 6938     (clear-stream $_test-input-buffered-file->buffer)
 6939     (clear-stream _test-output-stream)
 6940     (clear-stream $_test-output-buffered-file->buffer)
 6941     #
 6942     (write _test-input-stream "fn f {\n")
 6943     (write _test-input-stream "  var a: t\n")
 6944     (write _test-input-stream "  foo a\n")
 6945     (write _test-input-stream "}\n")
 6946     (write _test-input-stream "fn foo x: t {\n")
 6947     (write _test-input-stream "}\n")
 6948     (write _test-input-stream "type t {\n")
 6949     (write _test-input-stream "  x: int\n")
 6950     (write _test-input-stream "  y: int\n")
 6951     (write _test-input-stream "}\n")
 6952     # convert
 6953     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6954     (flush _test-output-buffered-file)
 6955 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6961     # check output
 6962     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-arg-of-user-defined-type/0")
 6963     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/1")
 6964     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/2")
 6965     (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")
 6966     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type/4")
 6967     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"     "F - test-convert-function-call-with-arg-of-user-defined-type/5")
 6968     # var a: t
 6969     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-call-with-arg-of-user-defined-type/6")
 6970     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-call-with-arg-of-user-defined-type/7")
 6971     # foo a
 6972     (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")
 6973     #
 6974     (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")
 6975     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type/10")
 6976     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"    "F - test-convert-function-call-with-arg-of-user-defined-type/11")
 6977     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/12")
 6978     (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")
 6979     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/14")
 6980     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/15")
 6981     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call-with-arg-of-user-defined-type/16")
 6982     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/17")
 6983     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/18")
 6984     (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")
 6985     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/20")
 6986     (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")
 6987     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/22")
 6988     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/23")
 6989     # . epilogue
 6990     89/<- %esp 5/r32/ebp
 6991     5d/pop-to-ebp
 6992     c3/return
 6993 
 6994 test-convert-function-call-with-arg-of-user-defined-type-register-indirect:
 6995     # . prologue
 6996     55/push-ebp
 6997     89/<- %ebp 4/r32/esp
 6998     # setup
 6999     (clear-stream _test-input-stream)
 7000     (clear-stream $_test-input-buffered-file->buffer)
 7001     (clear-stream _test-output-stream)
 7002     (clear-stream $_test-output-buffered-file->buffer)
 7003     #
 7004     (write _test-input-stream "fn f {\n")
 7005     (write _test-input-stream "  var a/eax: (addr t) <- copy 0\n")
 7006     (write _test-input-stream "  foo *a\n")
 7007     (write _test-input-stream "}\n")
 7008     (write _test-input-stream "fn foo x: t {\n")
 7009     (write _test-input-stream "}\n")
 7010     (write _test-input-stream "type t {\n")
 7011     (write _test-input-stream "  x: int\n")
 7012     (write _test-input-stream "  y: int\n")
 7013     (write _test-input-stream "}\n")
 7014     # convert
 7015     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7016     (flush _test-output-buffered-file)
 7017 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 7023     # check output
 7024     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-arg-of-user-defined-type/0")
 7025     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/1")
 7026     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/2")
 7027     (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")
 7028     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type/4")
 7029     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"     "F - test-convert-function-call-with-arg-of-user-defined-type/5")
 7030     # var a
 7031     (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")
 7032     (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")
 7033     # foo a
 7034     (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")
 7035     #
 7036     (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")
 7037     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type/10")
 7038     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"    "F - test-convert-function-call-with-arg-of-user-defined-type/11")
 7039     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/12")
 7040     (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")
 7041     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/14")
 7042     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/15")
 7043     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call-with-arg-of-user-defined-type/16")
 7044     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/17")
 7045     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/18")
 7046     (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")
 7047     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/20")
 7048     (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")
 7049     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/22")
 7050     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/23")
 7051     # . epilogue
 7052     89/<- %esp 5/r32/ebp
 7053     5d/pop-to-ebp
 7054     c3/return
 7055 
 7056 # we don't have special support for call-by-reference; just explicitly create
 7057 # a new variable with the address of the arg
 7058 test-convert-function-call-with-arg-of-user-defined-type-by-reference:
 7059     # . prologue
 7060     55/push-ebp
 7061     89/<- %ebp 4/r32/esp
 7062     # setup
 7063     (clear-stream _test-input-stream)
 7064     (clear-stream $_test-input-buffered-file->buffer)
 7065     (clear-stream _test-output-stream)
 7066     (clear-stream $_test-output-buffered-file->buffer)
 7067     #
 7068     (write _test-input-stream "fn f {\n")
 7069     (write _test-input-stream "  var a: t\n")
 7070     (write _test-input-stream "  var b/eax: (addr t) <- address a\n")
 7071     (write _test-input-stream "  foo b\n")
 7072     (write _test-input-stream "}\n")
 7073     (write _test-input-stream "fn foo x: (addr t) {\n")
 7074     (write _test-input-stream "  var x/ecx: (addr t) <- copy x\n")
 7075     (write _test-input-stream "}\n")
 7076     (write _test-input-stream "type t {\n")
 7077     (write _test-input-stream "  x: int\n")
 7078     (write _test-input-stream "  y: int\n")
 7079     (write _test-input-stream "}\n")
 7080     # convert
 7081     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7082     (flush _test-output-buffered-file)
 7083 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 7089     # check output
 7090     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/0")
 7091     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/1")
 7092     (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")
 7093     (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")
 7094     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/4")
 7095     (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")
 7096     # var a: t
 7097     (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")
 7098     (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")
 7099     # var b/eax: (addr t)
 7100     (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")
 7101     (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")
 7102     # foo a
 7103     (check-next-stream-line-equal _test-output-stream "    (foo %eax)"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/10")
 7104     #
 7105     (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")
 7106     (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")
 7107     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/13")
 7108     (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")
 7109     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/15")
 7110     (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")
 7111     (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")
 7112     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/18")
 7113     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/19")
 7114     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/20")
 7115     (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")
 7116     (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")
 7117     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/23")
 7118     (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")
 7119     (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")
 7120     (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")
 7121     (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")
 7122     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/28")
 7123     (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")
 7124     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/30")
 7125     (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")
 7126     (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")
 7127     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/33")
 7128     # . epilogue
 7129     89/<- %esp 5/r32/ebp
 7130     5d/pop-to-ebp
 7131     c3/return
 7132 
 7133 test-convert-get-on-local-variable:
 7134     # . prologue
 7135     55/push-ebp
 7136     89/<- %ebp 4/r32/esp
 7137     # setup
 7138     (clear-stream _test-input-stream)
 7139     (clear-stream $_test-input-buffered-file->buffer)
 7140     (clear-stream _test-output-stream)
 7141     (clear-stream $_test-output-buffered-file->buffer)
 7142     #
 7143     (write _test-input-stream "fn foo {\n")
 7144     (write _test-input-stream "  var a: t\n")
 7145     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 7146     (write _test-input-stream "}\n")
 7147     (write _test-input-stream "type t {\n")
 7148     (write _test-input-stream "  x: int\n")
 7149     (write _test-input-stream "  y: int\n")
 7150     (write _test-input-stream "}\n")
 7151     # convert
 7152     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7153     (flush _test-output-buffered-file)
 7154 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 7160     # check output
 7161     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-get-on-local-variable/0")
 7162     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-get-on-local-variable/1")
 7163     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-get-on-local-variable/2")
 7164     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-get-on-local-variable/3")
 7165     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-get-on-local-variable/4")
 7166     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-get-on-local-variable/5")
 7167     # var a
 7168     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-get-on-local-variable/6")
 7169     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-get-on-local-variable/7")
 7170     # var c
 7171     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-get-on-local-variable/8")
 7172     # get
 7173     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp+0xfffffffc) 0x00000001/r32"  "F - test-convert-get-on-local-variable/9")
 7174     # reclaim c
 7175     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-get-on-local-variable/10")
 7176     # reclaim a
 7177     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000008/imm32"  "F - test-convert-get-on-local-variable/11")
 7178     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-get-on-local-variable/12")
 7179     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-get-on-local-variable/13")
 7180     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-get-on-local-variable/14")
 7181     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-get-on-local-variable/15")
 7182     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-get-on-local-variable/16")
 7183     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-get-on-local-variable/17")
 7184     # . epilogue
 7185     89/<- %esp 5/r32/ebp
 7186     5d/pop-to-ebp
 7187     c3/return
 7188 
 7189 test-convert-get-on-function-argument:
 7190     # . prologue
 7191     55/push-ebp
 7192     89/<- %ebp 4/r32/esp
 7193     # setup
 7194     (clear-stream _test-input-stream)
 7195     (clear-stream $_test-input-buffered-file->buffer)
 7196     (clear-stream _test-output-stream)
 7197     (clear-stream $_test-output-buffered-file->buffer)
 7198     #
 7199     (write _test-input-stream "fn foo a: t {\n")
 7200     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 7201     (write _test-input-stream "}\n")
 7202     (write _test-input-stream "type t {\n")
 7203     (write _test-input-stream "  x: int\n")
 7204     (write _test-input-stream "  y: int\n")
 7205     (write _test-input-stream "}\n")
 7206     # convert
 7207     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7208     (flush _test-output-buffered-file)
 7209 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 7215     # check output
 7216     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-get-on-function-argument/0")
 7217     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-get-on-function-argument/1")
 7218     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-get-on-function-argument/2")
 7219     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-get-on-function-argument/3")
 7220     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-get-on-function-argument/4")
 7221     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-get-on-function-argument/5")
 7222     # var c
 7223     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-get-on-function-argument/6")
 7224     # get
 7225     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp+0x0000000c) 0x00000001/r32"  "F - test-convert-get-on-function-argument/7")
 7226     # reclaim c
 7227     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-get-on-function-argument/8")
 7228     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-get-on-function-argument/9")
 7229     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-get-on-function-argument/10")
 7230     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-get-on-function-argument/11")
 7231     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-get-on-function-argument/12")
 7232     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-get-on-function-argument/13")
 7233     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-get-on-function-argument/14")
 7234     # . epilogue
 7235     89/<- %esp 5/r32/ebp
 7236     5d/pop-to-ebp
 7237     c3/return
 7238 
 7239 test-convert-get-on-function-argument-with-known-type:
 7240     # . prologue
 7241     55/push-ebp
 7242     89/<- %ebp 4/r32/esp
 7243     # setup
 7244     (clear-stream _test-input-stream)
 7245     (clear-stream $_test-input-buffered-file->buffer)
 7246     (clear-stream _test-output-stream)
 7247     (clear-stream $_test-output-buffered-file->buffer)
 7248     #
 7249     (write _test-input-stream "type t {\n")
 7250     (write _test-input-stream "  x: int\n")
 7251     (write _test-input-stream "  y: int\n")
 7252     (write _test-input-stream "}\n")
 7253     (write _test-input-stream "fn foo a: t {\n")
 7254     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 7255     (write _test-input-stream "}\n")
 7256     # convert
 7257     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7258     (flush _test-output-buffered-file)
 7259 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 7265     # check output
 7266     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-get-on-function-argument-with-known-type/0")
 7267     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-get-on-function-argument-with-known-type/1")
 7268     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-get-on-function-argument-with-known-type/2")
 7269     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-get-on-function-argument-with-known-type/3")
 7270     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-get-on-function-argument-with-known-type/4")
 7271     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-get-on-function-argument-with-known-type/5")
 7272     # var c
 7273     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-get-on-function-argument-with-known-type/6")
 7274     # get
 7275     (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")
 7276     # reclaim c
 7277     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-get-on-function-argument-with-known-type/8")
 7278     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-get-on-function-argument-with-known-type/9")
 7279     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-get-on-function-argument-with-known-type/10")
 7280     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-get-on-function-argument-with-known-type/11")
 7281     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-get-on-function-argument-with-known-type/12")
 7282     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-get-on-function-argument-with-known-type/13")
 7283     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-get-on-function-argument-with-known-type/14")
 7284     # . epilogue
 7285     89/<- %esp 5/r32/ebp
 7286     5d/pop-to-ebp
 7287     c3/return
 7288 
 7289 test-add-with-too-many-inouts:
 7290     # . prologue
 7291     55/push-ebp
 7292     89/<- %ebp 4/r32/esp
 7293     # setup
 7294     (clear-stream _test-input-stream)
 7295     (clear-stream $_test-input-buffered-file->buffer)
 7296     (clear-stream _test-output-stream)
 7297     (clear-stream $_test-output-buffered-file->buffer)
 7298     (clear-stream _test-error-stream)
 7299     (clear-stream $_test-error-buffered-file->buffer)
 7300     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7301     68/push 0/imm32
 7302     68/push 0/imm32
 7303     89/<- %edx 4/r32/esp
 7304     (tailor-exit-descriptor %edx 0x10)
 7305     #
 7306     (write _test-input-stream "fn foo {\n")
 7307     (write _test-input-stream "  var a: int\n")
 7308     (write _test-input-stream "  var b/ecx: int <- add a, 0\n")
 7309     (write _test-input-stream "}\n")
 7310     # convert
 7311     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7312     # registers except esp clobbered at this point
 7313     # restore ed
 7314     89/<- %edx 4/r32/esp
 7315     (flush _test-output-buffered-file)
 7316     (flush _test-error-buffered-file)
 7317 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7323     # check output
 7324     (check-stream-equal _test-output-stream  ""  "F - test-add-with-too-many-inouts: output should be empty")
 7325     (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")
 7326     # check that stop(1) was called
 7327     (check-ints-equal *(edx+4) 2 "F - test-add-with-too-many-inouts: exit status")
 7328     # don't restore from ebp
 7329     81 0/subop/add %esp 8/imm32
 7330     # . epilogue
 7331     5d/pop-to-ebp
 7332     c3/return
 7333 
 7334 test-add-with-too-many-inouts-2:
 7335     # . prologue
 7336     55/push-ebp
 7337     89/<- %ebp 4/r32/esp
 7338     # setup
 7339     (clear-stream _test-input-stream)
 7340     (clear-stream $_test-input-buffered-file->buffer)
 7341     (clear-stream _test-output-stream)
 7342     (clear-stream $_test-output-buffered-file->buffer)
 7343     (clear-stream _test-error-stream)
 7344     (clear-stream $_test-error-buffered-file->buffer)
 7345     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7346     68/push 0/imm32
 7347     68/push 0/imm32
 7348     89/<- %edx 4/r32/esp
 7349     (tailor-exit-descriptor %edx 0x10)
 7350     #
 7351     (write _test-input-stream "fn foo {\n")
 7352     (write _test-input-stream "  var a: int\n")
 7353     (write _test-input-stream "  add-to a, 0, 1\n")
 7354     (write _test-input-stream "}\n")
 7355     # convert
 7356     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7357     # registers except esp clobbered at this point
 7358     # restore ed
 7359     89/<- %edx 4/r32/esp
 7360     (flush _test-output-buffered-file)
 7361     (flush _test-error-buffered-file)
 7362 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7368     # check output
 7369     (check-stream-equal _test-output-stream  ""  "F - test-add-with-too-many-inouts-2: output should be empty")
 7370     (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")
 7371     # check that stop(1) was called
 7372     (check-ints-equal *(edx+4) 2 "F - test-add-with-too-many-inouts-2: exit status")
 7373     # don't restore from ebp
 7374     81 0/subop/add %esp 8/imm32
 7375     # . epilogue
 7376     5d/pop-to-ebp
 7377     c3/return
 7378 
 7379 test-add-with-too-many-outputs:
 7380     # . prologue
 7381     55/push-ebp
 7382     89/<- %ebp 4/r32/esp
 7383     # setup
 7384     (clear-stream _test-input-stream)
 7385     (clear-stream $_test-input-buffered-file->buffer)
 7386     (clear-stream _test-output-stream)
 7387     (clear-stream $_test-output-buffered-file->buffer)
 7388     (clear-stream _test-error-stream)
 7389     (clear-stream $_test-error-buffered-file->buffer)
 7390     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7391     68/push 0/imm32
 7392     68/push 0/imm32
 7393     89/<- %edx 4/r32/esp
 7394     (tailor-exit-descriptor %edx 0x10)
 7395     #
 7396     (write _test-input-stream "fn foo {\n")
 7397     (write _test-input-stream "  var a/eax: int <- copy 0\n")
 7398     (write _test-input-stream "  var b/ebx: int <- copy 0\n")
 7399     (write _test-input-stream "  var c/ecx: int <- copy 0\n")
 7400     (write _test-input-stream "  c, b <- add a\n")
 7401     (write _test-input-stream "}\n")
 7402     # convert
 7403     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7404     # registers except esp clobbered at this point
 7405     # restore ed
 7406     89/<- %edx 4/r32/esp
 7407     (flush _test-output-buffered-file)
 7408     (flush _test-error-buffered-file)
 7409 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7415     # check output
 7416     (check-stream-equal _test-output-stream  ""  "F - test-add-with-too-many-outputs: output should be empty")
 7417     (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")
 7418     # check that stop(1) was called
 7419     (check-ints-equal *(edx+4) 2 "F - test-add-with-too-many-outputs: exit status")
 7420     # don't restore from ebp
 7421     81 0/subop/add %esp 8/imm32
 7422     # . epilogue
 7423     5d/pop-to-ebp
 7424     c3/return
 7425 
 7426 test-add-with-non-number:
 7427     # . prologue
 7428     55/push-ebp
 7429     89/<- %ebp 4/r32/esp
 7430     # setup
 7431     (clear-stream _test-input-stream)
 7432     (clear-stream $_test-input-buffered-file->buffer)
 7433     (clear-stream _test-output-stream)
 7434     (clear-stream $_test-output-buffered-file->buffer)
 7435     (clear-stream _test-error-stream)
 7436     (clear-stream $_test-error-buffered-file->buffer)
 7437     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7438     68/push 0/imm32
 7439     68/push 0/imm32
 7440     89/<- %edx 4/r32/esp
 7441     (tailor-exit-descriptor %edx 0x10)
 7442     #
 7443     (write _test-input-stream "fn foo {\n")
 7444     (write _test-input-stream "  var a: int\n")
 7445     (write _test-input-stream "  var b/ecx: (addr int) <- add a\n")
 7446     (write _test-input-stream "}\n")
 7447     # convert
 7448     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7449     # registers except esp clobbered at this point
 7450     # restore ed
 7451     89/<- %edx 4/r32/esp
 7452     (flush _test-output-buffered-file)
 7453     (flush _test-error-buffered-file)
 7454 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7460     # check output
 7461     (check-stream-equal _test-output-stream  ""  "F - test-add-with-non-number: output should be empty")
 7462     (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")
 7463     # check that stop(1) was called
 7464     (check-ints-equal *(edx+4) 2 "F - test-add-with-non-number: exit status")
 7465     # don't restore from ebp
 7466     81 0/subop/add %esp 8/imm32
 7467     # . epilogue
 7468     5d/pop-to-ebp
 7469     c3/return
 7470 
 7471 test-add-with-addr-dereferenced:
 7472     # . prologue
 7473     55/push-ebp
 7474     89/<- %ebp 4/r32/esp
 7475     # setup
 7476     (clear-stream _test-input-stream)
 7477     (clear-stream $_test-input-buffered-file->buffer)
 7478     (clear-stream _test-output-stream)
 7479     (clear-stream $_test-output-buffered-file->buffer)
 7480     #
 7481     (write _test-input-stream "fn foo {\n")
 7482     (write _test-input-stream "  var a/eax: (addr int) <- copy 0\n")
 7483     (write _test-input-stream "  add-to *a, 1\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     # no error
 7489     # . epilogue
 7490     89/<- %esp 5/r32/ebp
 7491     5d/pop-to-ebp
 7492     c3/return
 7493 
 7494 test-copy-with-no-inout:
 7495     # . prologue
 7496     55/push-ebp
 7497     89/<- %ebp 4/r32/esp
 7498     # setup
 7499     (clear-stream _test-input-stream)
 7500     (clear-stream $_test-input-buffered-file->buffer)
 7501     (clear-stream _test-output-stream)
 7502     (clear-stream $_test-output-buffered-file->buffer)
 7503     (clear-stream _test-error-stream)
 7504     (clear-stream $_test-error-buffered-file->buffer)
 7505     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7506     68/push 0/imm32
 7507     68/push 0/imm32
 7508     89/<- %edx 4/r32/esp
 7509     (tailor-exit-descriptor %edx 0x10)
 7510     #
 7511     (write _test-input-stream "fn foo {\n")
 7512     (write _test-input-stream "  var x/eax: boolean <- copy\n")
 7513     (write _test-input-stream "}\n")
 7514     # convert
 7515     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7516     # registers except esp clobbered at this point
 7517     # restore ed
 7518     89/<- %edx 4/r32/esp
 7519     (flush _test-output-buffered-file)
 7520     (flush _test-error-buffered-file)
 7521 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7527     # check output
 7528     (check-stream-equal _test-output-stream  ""  "F - test-copy-with-no-inout: output should be empty")
 7529     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy' expects an inout"  "F - test-copy-with-no-inout: error message")
 7530     # check that stop(1) was called
 7531     (check-ints-equal *(edx+4) 2 "F - test-copy-with-no-inout: exit status")
 7532     # don't restore from ebp
 7533     81 0/subop/add %esp 8/imm32
 7534     # . epilogue
 7535     5d/pop-to-ebp
 7536     c3/return
 7537 
 7538 test-copy-with-multiple-inouts:
 7539     # . prologue
 7540     55/push-ebp
 7541     89/<- %ebp 4/r32/esp
 7542     # setup
 7543     (clear-stream _test-input-stream)
 7544     (clear-stream $_test-input-buffered-file->buffer)
 7545     (clear-stream _test-output-stream)
 7546     (clear-stream $_test-output-buffered-file->buffer)
 7547     (clear-stream _test-error-stream)
 7548     (clear-stream $_test-error-buffered-file->buffer)
 7549     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7550     68/push 0/imm32
 7551     68/push 0/imm32
 7552     89/<- %edx 4/r32/esp
 7553     (tailor-exit-descriptor %edx 0x10)
 7554     #
 7555     (write _test-input-stream "fn foo {\n")
 7556     (write _test-input-stream "  var x/eax: boolean <- copy 0, 0\n")
 7557     (write _test-input-stream "}\n")
 7558     # convert
 7559     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7560     # registers except esp clobbered at this point
 7561     # restore ed
 7562     89/<- %edx 4/r32/esp
 7563     (flush _test-output-buffered-file)
 7564     (flush _test-error-buffered-file)
 7565 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7571     # check output
 7572     (check-stream-equal _test-output-stream  ""  "F - test-copy-with-multiple-inouts: output should be empty")
 7573     (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")
 7574     # check that stop(1) was called
 7575     (check-ints-equal *(edx+4) 2 "F - test-copy-with-multiple-inouts: exit status")
 7576     # don't restore from ebp
 7577     81 0/subop/add %esp 8/imm32
 7578     # . epilogue
 7579     5d/pop-to-ebp
 7580     c3/return
 7581 
 7582 test-copy-with-no-output:
 7583     # . prologue
 7584     55/push-ebp
 7585     89/<- %ebp 4/r32/esp
 7586     # setup
 7587     (clear-stream _test-input-stream)
 7588     (clear-stream $_test-input-buffered-file->buffer)
 7589     (clear-stream _test-output-stream)
 7590     (clear-stream $_test-output-buffered-file->buffer)
 7591     (clear-stream _test-error-stream)
 7592     (clear-stream $_test-error-buffered-file->buffer)
 7593     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7594     68/push 0/imm32
 7595     68/push 0/imm32
 7596     89/<- %edx 4/r32/esp
 7597     (tailor-exit-descriptor %edx 0x10)
 7598     #
 7599     (write _test-input-stream "fn foo {\n")
 7600     (write _test-input-stream "  copy 0\n")
 7601     (write _test-input-stream "}\n")
 7602     # convert
 7603     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7604     # registers except esp clobbered at this point
 7605     # restore ed
 7606     89/<- %edx 4/r32/esp
 7607     (flush _test-output-buffered-file)
 7608     (flush _test-error-buffered-file)
 7609 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7615     # check output
 7616     (check-stream-equal _test-output-stream  ""  "F - test-copy-with-no-output: output should be empty")
 7617     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy' expects an output"  "F - test-copy-with-no-output: error message")
 7618     # check that stop(1) was called
 7619     (check-ints-equal *(edx+4) 2 "F - test-copy-with-no-output: exit status")
 7620     # don't restore from ebp
 7621     81 0/subop/add %esp 8/imm32
 7622     # . epilogue
 7623     5d/pop-to-ebp
 7624     c3/return
 7625 
 7626 test-copy-with-multiple-outputs:
 7627     # . prologue
 7628     55/push-ebp
 7629     89/<- %ebp 4/r32/esp
 7630     # setup
 7631     (clear-stream _test-input-stream)
 7632     (clear-stream $_test-input-buffered-file->buffer)
 7633     (clear-stream _test-output-stream)
 7634     (clear-stream $_test-output-buffered-file->buffer)
 7635     (clear-stream _test-error-stream)
 7636     (clear-stream $_test-error-buffered-file->buffer)
 7637     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7638     68/push 0/imm32
 7639     68/push 0/imm32
 7640     89/<- %edx 4/r32/esp
 7641     (tailor-exit-descriptor %edx 0x10)
 7642     #
 7643     (write _test-input-stream "fn foo {\n")
 7644     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
 7645     (write _test-input-stream "  var y/ecx: boolean <- copy 0\n")
 7646     (write _test-input-stream "  x, y <- copy 0\n")
 7647     (write _test-input-stream "}\n")
 7648     # convert
 7649     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7650     # registers except esp clobbered at this point
 7651     # restore ed
 7652     89/<- %edx 4/r32/esp
 7653     (flush _test-output-buffered-file)
 7654     (flush _test-error-buffered-file)
 7655 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7661     # check output
 7662     (check-stream-equal _test-output-stream  ""  "F - test-copy-with-multiple-outputs: output should be empty")
 7663     (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")
 7664     # check that stop(1) was called
 7665     (check-ints-equal *(edx+4) 2 "F - test-copy-with-multiple-outputs: exit status")
 7666     # don't restore from ebp
 7667     81 0/subop/add %esp 8/imm32
 7668     # . epilogue
 7669     5d/pop-to-ebp
 7670     c3/return
 7671 
 7672 test-copy-invalid-value-to-address:
 7673     # . prologue
 7674     55/push-ebp
 7675     89/<- %ebp 4/r32/esp
 7676     # setup
 7677     (clear-stream _test-input-stream)
 7678     (clear-stream $_test-input-buffered-file->buffer)
 7679     (clear-stream _test-output-stream)
 7680     (clear-stream $_test-output-buffered-file->buffer)
 7681     (clear-stream _test-error-stream)
 7682     (clear-stream $_test-error-buffered-file->buffer)
 7683     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7684     68/push 0/imm32
 7685     68/push 0/imm32
 7686     89/<- %edx 4/r32/esp
 7687     (tailor-exit-descriptor %edx 0x10)
 7688     #
 7689     (write _test-input-stream "fn foo {\n")
 7690     (write _test-input-stream "  var x/eax: int <- copy 0\n")
 7691     (write _test-input-stream "  var y/ecx: (addr int) <- copy x\n")
 7692     (write _test-input-stream "}\n")
 7693     # convert
 7694     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7695     # registers except esp clobbered at this point
 7696     # restore ed
 7697     89/<- %edx 4/r32/esp
 7698     (flush _test-output-buffered-file)
 7699     (flush _test-error-buffered-file)
 7700 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7706     # check output
 7707     (check-stream-equal _test-output-stream  ""  "F - test-copy-invalid-value-to-address: output should be empty")
 7708     (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")
 7709     # check that stop(1) was called
 7710     (check-ints-equal *(edx+4) 2 "F - test-copy-invalid-value-to-address: exit status")
 7711     # don't restore from ebp
 7712     81 0/subop/add %esp 8/imm32
 7713     # . epilogue
 7714     5d/pop-to-ebp
 7715     c3/return
 7716 
 7717 test-copy-null-value-to-address:
 7718     # . prologue
 7719     55/push-ebp
 7720     89/<- %ebp 4/r32/esp
 7721     # setup
 7722     (clear-stream _test-input-stream)
 7723     (clear-stream $_test-input-buffered-file->buffer)
 7724     (clear-stream _test-output-stream)
 7725     (clear-stream $_test-output-buffered-file->buffer)
 7726     #
 7727     (write _test-input-stream "fn foo {\n")
 7728     (write _test-input-stream "  var y/ecx: (addr int) <- copy 0\n")
 7729     (write _test-input-stream "}\n")
 7730     # convert
 7731     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7732     (flush _test-output-buffered-file)
 7733     # no errors
 7734     # . epilogue
 7735     89/<- %esp 5/r32/ebp
 7736     5d/pop-to-ebp
 7737     c3/return
 7738 
 7739 test-copy-invalid-value-to-offset:
 7740     # . prologue
 7741     55/push-ebp
 7742     89/<- %ebp 4/r32/esp
 7743     # setup
 7744     (clear-stream _test-input-stream)
 7745     (clear-stream $_test-input-buffered-file->buffer)
 7746     (clear-stream _test-output-stream)
 7747     (clear-stream $_test-output-buffered-file->buffer)
 7748     (clear-stream _test-error-stream)
 7749     (clear-stream $_test-error-buffered-file->buffer)
 7750     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7751     68/push 0/imm32
 7752     68/push 0/imm32
 7753     89/<- %edx 4/r32/esp
 7754     (tailor-exit-descriptor %edx 0x10)
 7755     #
 7756     (write _test-input-stream "fn foo {\n")
 7757     (write _test-input-stream "  var x/eax: int <- copy 0\n")
 7758     (write _test-input-stream "  var y/ecx: (offset int) <- copy x\n")
 7759     (write _test-input-stream "}\n")
 7760     # convert
 7761     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7762     # registers except esp clobbered at this point
 7763     # restore ed
 7764     89/<- %edx 4/r32/esp
 7765     (flush _test-output-buffered-file)
 7766     (flush _test-error-buffered-file)
 7767 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7773     # check output
 7774     (check-stream-equal _test-output-stream  ""  "F - test-copy-invalid-value-to-address: output should be empty")
 7775     (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")
 7776     # check that stop(1) was called
 7777     (check-ints-equal *(edx+4) 2 "F - test-copy-invalid-value-to-offset: exit status")
 7778     # don't restore from ebp
 7779     81 0/subop/add %esp 8/imm32
 7780     # . epilogue
 7781     5d/pop-to-ebp
 7782     c3/return
 7783 
 7784 test-copy-null-value-to-offset:
 7785     # . prologue
 7786     55/push-ebp
 7787     89/<- %ebp 4/r32/esp
 7788     # setup
 7789     (clear-stream _test-input-stream)
 7790     (clear-stream $_test-input-buffered-file->buffer)
 7791     (clear-stream _test-output-stream)
 7792     (clear-stream $_test-output-buffered-file->buffer)
 7793     #
 7794     (write _test-input-stream "fn foo {\n")
 7795     (write _test-input-stream "  var y/ecx: (offset int) <- copy 0\n")
 7796     (write _test-input-stream "}\n")
 7797     # convert
 7798     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7799     (flush _test-output-buffered-file)
 7800 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7806     # no errors
 7807     # . epilogue
 7808     89/<- %esp 5/r32/ebp
 7809     5d/pop-to-ebp
 7810     c3/return
 7811 
 7812 test-copy-non-literal-to-byte:
 7813     # . prologue
 7814     55/push-ebp
 7815     89/<- %ebp 4/r32/esp
 7816     # setup
 7817     (clear-stream _test-input-stream)
 7818     (clear-stream $_test-input-buffered-file->buffer)
 7819     (clear-stream _test-output-stream)
 7820     (clear-stream $_test-output-buffered-file->buffer)
 7821     (clear-stream _test-error-stream)
 7822     (clear-stream $_test-error-buffered-file->buffer)
 7823     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7824     68/push 0/imm32
 7825     68/push 0/imm32
 7826     89/<- %edx 4/r32/esp
 7827     (tailor-exit-descriptor %edx 0x10)
 7828     #
 7829     (write _test-input-stream "fn foo {\n")
 7830     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 7831     (write _test-input-stream "  var y/ecx: byte <- copy x\n")
 7832     (write _test-input-stream "}\n")
 7833     # convert
 7834     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7835     # registers except esp clobbered at this point
 7836     # restore ed
 7837     89/<- %edx 4/r32/esp
 7838     (flush _test-output-buffered-file)
 7839     (flush _test-error-buffered-file)
 7840 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7846     # check output
 7847     (check-stream-equal _test-output-stream  ""  "F - test-copy-non-literal-to-byte: output should be empty")
 7848     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy: cannot copy non-literal to 'y' of type byte; use copy-byte"  "F - test-copy-non-literal-to-byte: error message")
 7849     # check that stop(1) was called
 7850     (check-ints-equal *(edx+4) 2 "F - test-copy-non-literal-to-byte: exit status")
 7851     # don't restore from ebp
 7852     81 0/subop/add %esp 8/imm32
 7853     # . epilogue
 7854     5d/pop-to-ebp
 7855     c3/return
 7856 
 7857 test-copy-deref-address:
 7858     # . prologue
 7859     55/push-ebp
 7860     89/<- %ebp 4/r32/esp
 7861     # setup
 7862     (clear-stream _test-input-stream)
 7863     (clear-stream $_test-input-buffered-file->buffer)
 7864     (clear-stream _test-output-stream)
 7865     (clear-stream $_test-output-buffered-file->buffer)
 7866     #
 7867     (write _test-input-stream "fn foo {\n")
 7868     (write _test-input-stream "  var x/eax: (addr addr int) <- copy 0\n")
 7869     (write _test-input-stream "  var y/ecx: (addr int) <- copy *x\n")
 7870     (write _test-input-stream "}\n")
 7871     # convert
 7872     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7873     (flush _test-output-buffered-file)
 7874     # no errors
 7875     # . epilogue
 7876     5d/pop-to-ebp
 7877     c3/return
 7878 
 7879 test-copy-to-non-register:
 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: int\n")
 7898     (write _test-input-stream "  x <- copy 0\n")
 7899     (write _test-input-stream "}\n")
 7900     # convert
 7901     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7902     # registers except esp clobbered at this point
 7903     # restore ed
 7904     89/<- %edx 4/r32/esp
 7905     (flush _test-output-buffered-file)
 7906     (flush _test-error-buffered-file)
 7907 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7913     # check output
 7914     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-non-register: output should be empty")
 7915     (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")
 7916     # check that stop(1) was called
 7917     (check-ints-equal *(edx+4) 2 "F - test-copy-to-non-register: exit status")
 7918     # don't restore from ebp
 7919     81 0/subop/add %esp 8/imm32
 7920     # . epilogue
 7921     5d/pop-to-ebp
 7922     c3/return
 7923 
 7924 test-copy-from-non-scalar-inout:
 7925     # . prologue
 7926     55/push-ebp
 7927     89/<- %ebp 4/r32/esp
 7928     # setup
 7929     (clear-stream _test-input-stream)
 7930     (clear-stream $_test-input-buffered-file->buffer)
 7931     (clear-stream _test-output-stream)
 7932     (clear-stream $_test-output-buffered-file->buffer)
 7933     (clear-stream _test-error-stream)
 7934     (clear-stream $_test-error-buffered-file->buffer)
 7935     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7936     68/push 0/imm32
 7937     68/push 0/imm32
 7938     89/<- %edx 4/r32/esp
 7939     (tailor-exit-descriptor %edx 0x10)
 7940     #
 7941     (write _test-input-stream "fn foo {\n")
 7942     (write _test-input-stream "  var x: (handle int)\n")
 7943     (write _test-input-stream "  var y/eax: int <- copy x\n")
 7944     (write _test-input-stream "}\n")
 7945     # convert
 7946     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7947     # registers except esp clobbered at this point
 7948     # restore ed
 7949     89/<- %edx 4/r32/esp
 7950     (flush _test-output-buffered-file)
 7951     (flush _test-error-buffered-file)
 7952 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7958     # check output
 7959     (check-stream-equal _test-output-stream  ""  "F - test-copy-from-non-scalar-inout: output should be empty")
 7960     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy: 'x' is too large to fit in a register"  "F - test-copy-from-non-scalar-inout: error message")
 7961     # check that stop(1) was called
 7962     (check-ints-equal *(edx+4) 2 "F - test-copy-from-non-scalar-inout: exit status")
 7963     # don't restore from ebp
 7964     81 0/subop/add %esp 8/imm32
 7965     # . epilogue
 7966     5d/pop-to-ebp
 7967     c3/return
 7968 
 7969 test-copy-to-with-no-inout:
 7970     # . prologue
 7971     55/push-ebp
 7972     89/<- %ebp 4/r32/esp
 7973     # setup
 7974     (clear-stream _test-input-stream)
 7975     (clear-stream $_test-input-buffered-file->buffer)
 7976     (clear-stream _test-output-stream)
 7977     (clear-stream $_test-output-buffered-file->buffer)
 7978     (clear-stream _test-error-stream)
 7979     (clear-stream $_test-error-buffered-file->buffer)
 7980     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7981     68/push 0/imm32
 7982     68/push 0/imm32
 7983     89/<- %edx 4/r32/esp
 7984     (tailor-exit-descriptor %edx 0x10)
 7985     #
 7986     (write _test-input-stream "fn foo {\n")
 7987     (write _test-input-stream "  copy-to\n")
 7988     (write _test-input-stream "}\n")
 7989     # convert
 7990     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7991     # registers except esp clobbered at this point
 7992     # restore ed
 7993     89/<- %edx 4/r32/esp
 7994     (flush _test-output-buffered-file)
 7995     (flush _test-error-buffered-file)
 7996 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8002     # check output
 8003     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-with-no-inout: output should be empty")
 8004     (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")
 8005     # check that stop(1) was called
 8006     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-no-inout: exit status")
 8007     # don't restore from ebp
 8008     81 0/subop/add %esp 8/imm32
 8009     # . epilogue
 8010     5d/pop-to-ebp
 8011     c3/return
 8012 
 8013 test-copy-to-with-no-source:
 8014     # . prologue
 8015     55/push-ebp
 8016     89/<- %ebp 4/r32/esp
 8017     # setup
 8018     (clear-stream _test-input-stream)
 8019     (clear-stream $_test-input-buffered-file->buffer)
 8020     (clear-stream _test-output-stream)
 8021     (clear-stream $_test-output-buffered-file->buffer)
 8022     (clear-stream _test-error-stream)
 8023     (clear-stream $_test-error-buffered-file->buffer)
 8024     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8025     68/push 0/imm32
 8026     68/push 0/imm32
 8027     89/<- %edx 4/r32/esp
 8028     (tailor-exit-descriptor %edx 0x10)
 8029     #
 8030     (write _test-input-stream "fn foo {\n")
 8031     (write _test-input-stream "  var x: boolean\n")
 8032     (write _test-input-stream "  copy-to x\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-copy-to-with-no-source: output should be empty")
 8049     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-to' must have two inouts"  "F - test-copy-to-with-no-source: error message")
 8050     # check that stop(1) was called
 8051     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-no-source: 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-copy-to-with-no-register:
 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: boolean\n")
 8077     (write _test-input-stream "  copy-to x, x\n")
 8078     (write _test-input-stream "}\n")
 8079     # convert
 8080     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8081     # registers except esp clobbered at this point
 8082     # restore ed
 8083     89/<- %edx 4/r32/esp
 8084     (flush _test-output-buffered-file)
 8085     (flush _test-error-buffered-file)
 8086 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8092     # check output
 8093     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-with-no-register: output should be empty")
 8094     (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")
 8095     # check that stop(1) was called
 8096     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-no-register: exit status")
 8097     # don't restore from ebp
 8098     81 0/subop/add %esp 8/imm32
 8099     # . epilogue
 8100     5d/pop-to-ebp
 8101     c3/return
 8102 
 8103 test-copy-to-with-too-many-inouts:
 8104     # . prologue
 8105     55/push-ebp
 8106     89/<- %ebp 4/r32/esp
 8107     # setup
 8108     (clear-stream _test-input-stream)
 8109     (clear-stream $_test-input-buffered-file->buffer)
 8110     (clear-stream _test-output-stream)
 8111     (clear-stream $_test-output-buffered-file->buffer)
 8112     (clear-stream _test-error-stream)
 8113     (clear-stream $_test-error-buffered-file->buffer)
 8114     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8115     68/push 0/imm32
 8116     68/push 0/imm32
 8117     89/<- %edx 4/r32/esp
 8118     (tailor-exit-descriptor %edx 0x10)
 8119     #
 8120     (write _test-input-stream "fn foo {\n")
 8121     (write _test-input-stream "  var x: boolean\n")
 8122     (write _test-input-stream "  copy-to x, 0, 0\n")
 8123     (write _test-input-stream "}\n")
 8124     # convert
 8125     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8126     # registers except esp clobbered at this point
 8127     # restore ed
 8128     89/<- %edx 4/r32/esp
 8129     (flush _test-output-buffered-file)
 8130     (flush _test-error-buffered-file)
 8131 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8137     # check output
 8138     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-with-too-many-inouts: output should be empty")
 8139     (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")
 8140     # check that stop(1) was called
 8141     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-too-many-inouts: exit status")
 8142     # don't restore from ebp
 8143     81 0/subop/add %esp 8/imm32
 8144     # . epilogue
 8145     5d/pop-to-ebp
 8146     c3/return
 8147 
 8148 test-copy-to-with-output:
 8149     # . prologue
 8150     55/push-ebp
 8151     89/<- %ebp 4/r32/esp
 8152     # setup
 8153     (clear-stream _test-input-stream)
 8154     (clear-stream $_test-input-buffered-file->buffer)
 8155     (clear-stream _test-output-stream)
 8156     (clear-stream $_test-output-buffered-file->buffer)
 8157     (clear-stream _test-error-stream)
 8158     (clear-stream $_test-error-buffered-file->buffer)
 8159     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8160     68/push 0/imm32
 8161     68/push 0/imm32
 8162     89/<- %edx 4/r32/esp
 8163     (tailor-exit-descriptor %edx 0x10)
 8164     #
 8165     (write _test-input-stream "fn foo {\n")
 8166     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
 8167     (write _test-input-stream "  var y/ecx: boolean <- copy 0\n")
 8168     (write _test-input-stream "  x <- copy-to y, 0\n")
 8169     (write _test-input-stream "}\n")
 8170     # convert
 8171     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8172     # registers except esp clobbered at this point
 8173     # restore ed
 8174     89/<- %edx 4/r32/esp
 8175     (flush _test-output-buffered-file)
 8176     (flush _test-error-buffered-file)
 8177 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8183     # check output
 8184     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-with-output: output should be empty")
 8185     (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")
 8186     # check that stop(1) was called
 8187     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-output: exit status")
 8188     # don't restore from ebp
 8189     81 0/subop/add %esp 8/imm32
 8190     # . epilogue
 8191     5d/pop-to-ebp
 8192     c3/return
 8193 
 8194 test-copy-to-invalid-value-to-address:
 8195     # . prologue
 8196     55/push-ebp
 8197     89/<- %ebp 4/r32/esp
 8198     # setup
 8199     (clear-stream _test-input-stream)
 8200     (clear-stream $_test-input-buffered-file->buffer)
 8201     (clear-stream _test-output-stream)
 8202     (clear-stream $_test-output-buffered-file->buffer)
 8203     (clear-stream _test-error-stream)
 8204     (clear-stream $_test-error-buffered-file->buffer)
 8205     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8206     68/push 0/imm32
 8207     68/push 0/imm32
 8208     89/<- %edx 4/r32/esp
 8209     (tailor-exit-descriptor %edx 0x10)
 8210     #
 8211     (write _test-input-stream "fn foo {\n")
 8212     (write _test-input-stream "  var x/eax: int <- copy 0\n")
 8213     (write _test-input-stream "  var y: (addr int)\n")
 8214     (write _test-input-stream "  copy-to y, x\n")
 8215     (write _test-input-stream "}\n")
 8216     # convert
 8217     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8218     # registers except esp clobbered at this point
 8219     # restore ed
 8220     89/<- %edx 4/r32/esp
 8221     (flush _test-output-buffered-file)
 8222     (flush _test-error-buffered-file)
 8223 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8229     # check output
 8230     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-invalid-value-to-address: output should be empty")
 8231     (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")
 8232     # check that stop(1) was called
 8233     (check-ints-equal *(edx+4) 2 "F - test-copy-to-invalid-value-to-address: exit status")
 8234     # don't restore from ebp
 8235     81 0/subop/add %esp 8/imm32
 8236     # . epilogue
 8237     5d/pop-to-ebp
 8238     c3/return
 8239 
 8240 test-copy-to-null-value-to-address:
 8241     # . prologue
 8242     55/push-ebp
 8243     89/<- %ebp 4/r32/esp
 8244     # setup
 8245     (clear-stream _test-input-stream)
 8246     (clear-stream $_test-input-buffered-file->buffer)
 8247     (clear-stream _test-output-stream)
 8248     (clear-stream $_test-output-buffered-file->buffer)
 8249     #
 8250     (write _test-input-stream "fn foo {\n")
 8251     (write _test-input-stream "  var y: (addr int)\n")
 8252     (write _test-input-stream "  copy-to y, 0\n")
 8253     (write _test-input-stream "}\n")
 8254     # convert
 8255     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 8256     (flush _test-output-buffered-file)
 8257     # no errors
 8258     # . epilogue
 8259     89/<- %esp 5/r32/ebp
 8260     5d/pop-to-ebp
 8261     c3/return
 8262 
 8263 test-copy-to-invalid-value-to-offset:
 8264     # . prologue
 8265     55/push-ebp
 8266     89/<- %ebp 4/r32/esp
 8267     # setup
 8268     (clear-stream _test-input-stream)
 8269     (clear-stream $_test-input-buffered-file->buffer)
 8270     (clear-stream _test-output-stream)
 8271     (clear-stream $_test-output-buffered-file->buffer)
 8272     (clear-stream _test-error-stream)
 8273     (clear-stream $_test-error-buffered-file->buffer)
 8274     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8275     68/push 0/imm32
 8276     68/push 0/imm32
 8277     89/<- %edx 4/r32/esp
 8278     (tailor-exit-descriptor %edx 0x10)
 8279     #
 8280     (write _test-input-stream "fn foo {\n")
 8281     (write _test-input-stream "  var x/eax: int <- copy 0\n")
 8282     (write _test-input-stream "  var y: (offset int)\n")
 8283     (write _test-input-stream "  copy-to y, x\n")
 8284     (write _test-input-stream "}\n")
 8285     # convert
 8286     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8287     # registers except esp clobbered at this point
 8288     # restore ed
 8289     89/<- %edx 4/r32/esp
 8290     (flush _test-output-buffered-file)
 8291     (flush _test-error-buffered-file)
 8292 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8298     # check output
 8299     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-invalid-value-to-offset: output should be empty")
 8300     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-to: 'y' must be a non-addr non-offset scalar"  "F - test-copy-to-invalid-value-to-offset: error message")
 8301     # check that stop(1) was called
 8302     (check-ints-equal *(edx+4) 2 "F - test-copy-to-invalid-value-to-offset: exit status")
 8303     # don't restore from ebp
 8304     81 0/subop/add %esp 8/imm32
 8305     # . epilogue
 8306     5d/pop-to-ebp
 8307     c3/return
 8308 
 8309 test-copy-to-null-value-to-offset:
 8310     # . prologue
 8311     55/push-ebp
 8312     89/<- %ebp 4/r32/esp
 8313     # setup
 8314     (clear-stream _test-input-stream)
 8315     (clear-stream $_test-input-buffered-file->buffer)
 8316     (clear-stream _test-output-stream)
 8317     (clear-stream $_test-output-buffered-file->buffer)
 8318     #
 8319     (write _test-input-stream "fn foo {\n")
 8320     (write _test-input-stream "  var y: (offset int)\n")
 8321     (write _test-input-stream "  copy-to y, 0\n")
 8322     (write _test-input-stream "}\n")
 8323     # convert
 8324     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 8325     (flush _test-output-buffered-file)
 8326     # no errors
 8327     # . epilogue
 8328     89/<- %esp 5/r32/ebp
 8329     5d/pop-to-ebp
 8330     c3/return
 8331 
 8332 test-copy-to-non-literal-to-byte:
 8333     # . prologue
 8334     55/push-ebp
 8335     89/<- %ebp 4/r32/esp
 8336     # setup
 8337     (clear-stream _test-input-stream)
 8338     (clear-stream $_test-input-buffered-file->buffer)
 8339     (clear-stream _test-output-stream)
 8340     (clear-stream $_test-output-buffered-file->buffer)
 8341     (clear-stream _test-error-stream)
 8342     (clear-stream $_test-error-buffered-file->buffer)
 8343     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8344     68/push 0/imm32
 8345     68/push 0/imm32
 8346     89/<- %edx 4/r32/esp
 8347     (tailor-exit-descriptor %edx 0x10)
 8348     #
 8349     (write _test-input-stream "fn foo {\n")
 8350     (write _test-input-stream "  var x/ecx: byte <- copy 3\n")
 8351     (write _test-input-stream "  var y/eax: (addr byte) <- copy 0\n")
 8352     (write _test-input-stream "  copy-to *y, x\n")
 8353     (write _test-input-stream "}\n")
 8354     # convert
 8355     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8356     # registers except esp clobbered at this point
 8357     # restore ed
 8358     89/<- %edx 4/r32/esp
 8359     (flush _test-output-buffered-file)
 8360     (flush _test-error-buffered-file)
 8361 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8367     # check output
 8368     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-non-literal-to-byte: output should be empty")
 8369     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-to: cannot copy non-literal to type byte; use copy-byte-to"  "F - test-copy-to-non-literal-to-byte: error message")
 8370     # check that stop(1) was called
 8371     (check-ints-equal *(edx+4) 2 "F - test-copy-to-non-literal-to-byte: exit status")
 8372     # don't restore from ebp
 8373     81 0/subop/add %esp 8/imm32
 8374     # . epilogue
 8375     5d/pop-to-ebp
 8376     c3/return
 8377 
 8378 test-copy-to-deref-address:
 8379     # . prologue
 8380     55/push-ebp
 8381     89/<- %ebp 4/r32/esp
 8382     # setup
 8383     (clear-stream _test-input-stream)
 8384     (clear-stream $_test-input-buffered-file->buffer)
 8385     (clear-stream _test-output-stream)
 8386     (clear-stream $_test-output-buffered-file->buffer)
 8387     #
 8388     (write _test-input-stream "fn foo {\n")
 8389     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
 8390     (write _test-input-stream "  var y/ecx: (addr addr int) <- copy 0\n")
 8391     (write _test-input-stream "  copy-to *y, x\n")
 8392     (write _test-input-stream "}\n")
 8393     # convert
 8394     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 8395     (flush _test-output-buffered-file)
 8396     # no errors
 8397     # . epilogue
 8398     5d/pop-to-ebp
 8399     c3/return
 8400 
 8401 test-copy-to-from-non-scalar-inout:
 8402     # . prologue
 8403     55/push-ebp
 8404     89/<- %ebp 4/r32/esp
 8405     # setup
 8406     (clear-stream _test-input-stream)
 8407     (clear-stream $_test-input-buffered-file->buffer)
 8408     (clear-stream _test-output-stream)
 8409     (clear-stream $_test-output-buffered-file->buffer)
 8410     (clear-stream _test-error-stream)
 8411     (clear-stream $_test-error-buffered-file->buffer)
 8412     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8413     68/push 0/imm32
 8414     68/push 0/imm32
 8415     89/<- %edx 4/r32/esp
 8416     (tailor-exit-descriptor %edx 0x10)
 8417     #
 8418     (write _test-input-stream "fn foo {\n")
 8419     (write _test-input-stream "  var x: (handle int)\n")
 8420     (write _test-input-stream "  var y: int\n")
 8421     (write _test-input-stream "  copy-to y, x\n")
 8422     (write _test-input-stream "}\n")
 8423     # convert
 8424     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8425     # registers except esp clobbered at this point
 8426     # restore ed
 8427     89/<- %edx 4/r32/esp
 8428     (flush _test-output-buffered-file)
 8429     (flush _test-error-buffered-file)
 8430 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8436     # check output
 8437     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-from-non-scalar-inout: output should be empty")
 8438     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-to: 'x' is too large to copy"  "F - test-copy-to-from-non-scalar-inout: error message")
 8439     # check that stop(1) was called
 8440     (check-ints-equal *(edx+4) 2 "F - test-copy-to-from-non-scalar-inout: exit status")
 8441     # don't restore from ebp
 8442     81 0/subop/add %esp 8/imm32
 8443     # . epilogue
 8444     5d/pop-to-ebp
 8445     c3/return
 8446 
 8447 test-copy-byte-with-no-inout:
 8448     # . prologue
 8449     55/push-ebp
 8450     89/<- %ebp 4/r32/esp
 8451     # setup
 8452     (clear-stream _test-input-stream)
 8453     (clear-stream $_test-input-buffered-file->buffer)
 8454     (clear-stream _test-output-stream)
 8455     (clear-stream $_test-output-buffered-file->buffer)
 8456     (clear-stream _test-error-stream)
 8457     (clear-stream $_test-error-buffered-file->buffer)
 8458     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8459     68/push 0/imm32
 8460     68/push 0/imm32
 8461     89/<- %edx 4/r32/esp
 8462     (tailor-exit-descriptor %edx 0x10)
 8463     #
 8464     (write _test-input-stream "fn foo {\n")
 8465     (write _test-input-stream "  var x/eax: byte <- copy-byte\n")
 8466     (write _test-input-stream "}\n")
 8467     # convert
 8468     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8469     # registers except esp clobbered at this point
 8470     # restore ed
 8471     89/<- %edx 4/r32/esp
 8472     (flush _test-output-buffered-file)
 8473     (flush _test-error-buffered-file)
 8474 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8480     # check output
 8481     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-with-no-inout: output should be empty")
 8482     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-byte' expects an inout"  "F - test-copy-byte-with-no-inout: error message")
 8483     # check that stop(1) was called
 8484     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-with-no-inout: exit status")
 8485     # don't restore from ebp
 8486     81 0/subop/add %esp 8/imm32
 8487     # . epilogue
 8488     5d/pop-to-ebp
 8489     c3/return
 8490 
 8491 test-copy-byte-with-multiple-inouts:
 8492     # . prologue
 8493     55/push-ebp
 8494     89/<- %ebp 4/r32/esp
 8495     # setup
 8496     (clear-stream _test-input-stream)
 8497     (clear-stream $_test-input-buffered-file->buffer)
 8498     (clear-stream _test-output-stream)
 8499     (clear-stream $_test-output-buffered-file->buffer)
 8500     (clear-stream _test-error-stream)
 8501     (clear-stream $_test-error-buffered-file->buffer)
 8502     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8503     68/push 0/imm32
 8504     68/push 0/imm32
 8505     89/<- %edx 4/r32/esp
 8506     (tailor-exit-descriptor %edx 0x10)
 8507     #
 8508     (write _test-input-stream "fn foo {\n")
 8509     (write _test-input-stream "  var x/eax: byte <- copy-byte 0, 0\n")
 8510     (write _test-input-stream "}\n")
 8511     # convert
 8512     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8513     # registers except esp clobbered at this point
 8514     # restore ed
 8515     89/<- %edx 4/r32/esp
 8516     (flush _test-output-buffered-file)
 8517     (flush _test-error-buffered-file)
 8518 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8524     # check output
 8525     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-with-multiple-inouts: output should be empty")
 8526     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-byte' must have just one inout"  "F - test-copy-byte-with-multiple-inouts: error message")
 8527     # check that stop(1) was called
 8528     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-with-multiple-inouts: exit status")
 8529     # don't restore from ebp
 8530     81 0/subop/add %esp 8/imm32
 8531     # . epilogue
 8532     5d/pop-to-ebp
 8533     c3/return
 8534 
 8535 test-copy-byte-with-no-output:
 8536     # . prologue
 8537     55/push-ebp
 8538     89/<- %ebp 4/r32/esp
 8539     # setup
 8540     (clear-stream _test-input-stream)
 8541     (clear-stream $_test-input-buffered-file->buffer)
 8542     (clear-stream _test-output-stream)
 8543     (clear-stream $_test-output-buffered-file->buffer)
 8544     (clear-stream _test-error-stream)
 8545     (clear-stream $_test-error-buffered-file->buffer)
 8546     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8547     68/push 0/imm32
 8548     68/push 0/imm32
 8549     89/<- %edx 4/r32/esp
 8550     (tailor-exit-descriptor %edx 0x10)
 8551     #
 8552     (write _test-input-stream "fn foo {\n")
 8553     (write _test-input-stream "  copy-byte 0\n")
 8554     (write _test-input-stream "}\n")
 8555     # convert
 8556     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8557     # registers except esp clobbered at this point
 8558     # restore ed
 8559     89/<- %edx 4/r32/esp
 8560     (flush _test-output-buffered-file)
 8561     (flush _test-error-buffered-file)
 8562 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8568     # check output
 8569     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-with-no-output: output should be empty")
 8570     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-byte' expects an output"  "F - test-copy-byte-with-no-output: error message")
 8571     # check that stop(1) was called
 8572     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-with-no-output: exit status")
 8573     # don't restore from ebp
 8574     81 0/subop/add %esp 8/imm32
 8575     # . epilogue
 8576     5d/pop-to-ebp
 8577     c3/return
 8578 
 8579 test-copy-byte-with-multiple-outputs:
 8580     # . prologue
 8581     55/push-ebp
 8582     89/<- %ebp 4/r32/esp
 8583     # setup
 8584     (clear-stream _test-input-stream)
 8585     (clear-stream $_test-input-buffered-file->buffer)
 8586     (clear-stream _test-output-stream)
 8587     (clear-stream $_test-output-buffered-file->buffer)
 8588     (clear-stream _test-error-stream)
 8589     (clear-stream $_test-error-buffered-file->buffer)
 8590     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8591     68/push 0/imm32
 8592     68/push 0/imm32
 8593     89/<- %edx 4/r32/esp
 8594     (tailor-exit-descriptor %edx 0x10)
 8595     #
 8596     (write _test-input-stream "fn foo {\n")
 8597     (write _test-input-stream "  var x/eax: byte <- copy 0\n")
 8598     (write _test-input-stream "  var y/ecx: byte <- copy 0\n")
 8599     (write _test-input-stream "  x, y <- copy-byte 0\n")
 8600     (write _test-input-stream "}\n")
 8601     # convert
 8602     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8603     # registers except esp clobbered at this point
 8604     # restore ed
 8605     89/<- %edx 4/r32/esp
 8606     (flush _test-output-buffered-file)
 8607     (flush _test-error-buffered-file)
 8608 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8614     # check output
 8615     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-with-multiple-outputs: output should be empty")
 8616     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-byte' must have just one output"  "F - test-copy-byte-with-multiple-outputs: error message")
 8617     # check that stop(1) was called
 8618     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-with-multiple-outputs: exit status")
 8619     # don't restore from ebp
 8620     81 0/subop/add %esp 8/imm32
 8621     # . epilogue
 8622     5d/pop-to-ebp
 8623     c3/return
 8624 
 8625 test-copy-byte-deref-address:
 8626     # . prologue
 8627     55/push-ebp
 8628     89/<- %ebp 4/r32/esp
 8629     # setup
 8630     (clear-stream _test-input-stream)
 8631     (clear-stream $_test-input-buffered-file->buffer)
 8632     (clear-stream _test-output-stream)
 8633     (clear-stream $_test-output-buffered-file->buffer)
 8634     #
 8635     (write _test-input-stream "fn foo {\n")
 8636     (write _test-input-stream "  var x/eax: (addr byte) <- copy 0\n")
 8637     (write _test-input-stream "  var y/ecx: byte <- copy-byte *x\n")
 8638     (write _test-input-stream "}\n")
 8639     # convert
 8640     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 8641     (flush _test-output-buffered-file)
 8642 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8648     # not bothering checking output
 8649     (check-next-stream-line-equal _test-error-stream  ""  "F - test-copy-byte-deref-address: error message")
 8650     # . epilogue
 8651     5d/pop-to-ebp
 8652     c3/return
 8653 
 8654 test-copy-byte-with-invalid-output-type:
 8655     # . prologue
 8656     55/push-ebp
 8657     89/<- %ebp 4/r32/esp
 8658     # setup
 8659     (clear-stream _test-input-stream)
 8660     (clear-stream $_test-input-buffered-file->buffer)
 8661     (clear-stream _test-output-stream)
 8662     (clear-stream $_test-output-buffered-file->buffer)
 8663     (clear-stream _test-error-stream)
 8664     (clear-stream $_test-error-buffered-file->buffer)
 8665     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8666     68/push 0/imm32
 8667     68/push 0/imm32
 8668     89/<- %edx 4/r32/esp
 8669     (tailor-exit-descriptor %edx 0x10)
 8670     #
 8671     (write _test-input-stream "fn foo {\n")
 8672     (write _test-input-stream "  var x/eax: (addr byte) <- copy 0\n")
 8673     (write _test-input-stream "  var y/eax: int <- copy-byte *x\n")
 8674     (write _test-input-stream "}\n")
 8675     # convert
 8676     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8677     # registers except esp clobbered at this point
 8678     # restore ed
 8679     89/<- %edx 4/r32/esp
 8680     (flush _test-output-buffered-file)
 8681     (flush _test-error-buffered-file)
 8682 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8688     # check output
 8689     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-with-invalid-output-type: output should be empty")
 8690     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-byte' must write to output of type byte"  "F - test-copy-byte-with-invalid-output-type: error message")
 8691     # check that stop(1) was called
 8692     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-with-invalid-output-type: exit status")
 8693     # don't restore from ebp
 8694     81 0/subop/add %esp 8/imm32
 8695     # . epilogue
 8696     5d/pop-to-ebp
 8697     c3/return
 8698 
 8699 test-copy-byte-from-non-scalar-inout:
 8700     # . prologue
 8701     55/push-ebp
 8702     89/<- %ebp 4/r32/esp
 8703     # setup
 8704     (clear-stream _test-input-stream)
 8705     (clear-stream $_test-input-buffered-file->buffer)
 8706     (clear-stream _test-output-stream)
 8707     (clear-stream $_test-output-buffered-file->buffer)
 8708     (clear-stream _test-error-stream)
 8709     (clear-stream $_test-error-buffered-file->buffer)
 8710     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8711     68/push 0/imm32
 8712     68/push 0/imm32
 8713     89/<- %edx 4/r32/esp
 8714     (tailor-exit-descriptor %edx 0x10)
 8715     #
 8716     (write _test-input-stream "fn foo {\n")
 8717     (write _test-input-stream "  var x: (handle int)\n")
 8718     (write _test-input-stream "  var y/eax: byte <- copy-byte x\n")
 8719     (write _test-input-stream "}\n")
 8720     # convert
 8721     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8722     # registers except esp clobbered at this point
 8723     # restore ed
 8724     89/<- %edx 4/r32/esp
 8725     (flush _test-output-buffered-file)
 8726     (flush _test-error-buffered-file)
 8727 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8733     # check output
 8734     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-from-non-scalar-inout: output should be empty")
 8735     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-byte: 'x' is too large to fit in a register"  "F - test-copy-byte-from-non-scalar-inout: error message")
 8736     # check that stop(1) was called
 8737     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-from-non-scalar-inout: exit status")
 8738     # don't restore from ebp
 8739     81 0/subop/add %esp 8/imm32
 8740     # . epilogue
 8741     5d/pop-to-ebp
 8742     c3/return
 8743 
 8744 test-copy-byte-to-with-no-inout:
 8745     # . prologue
 8746     55/push-ebp
 8747     89/<- %ebp 4/r32/esp
 8748     # setup
 8749     (clear-stream _test-input-stream)
 8750     (clear-stream $_test-input-buffered-file->buffer)
 8751     (clear-stream _test-output-stream)
 8752     (clear-stream $_test-output-buffered-file->buffer)
 8753     (clear-stream _test-error-stream)
 8754     (clear-stream $_test-error-buffered-file->buffer)
 8755     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8756     68/push 0/imm32
 8757     68/push 0/imm32
 8758     89/<- %edx 4/r32/esp
 8759     (tailor-exit-descriptor %edx 0x10)
 8760     #
 8761     (write _test-input-stream "fn foo {\n")
 8762     (write _test-input-stream "  copy-byte-to\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-copy-byte-to-with-no-inout: output should be empty")
 8779     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-byte-to' must have two inouts"  "F - test-copy-byte-to-with-no-inout: error message")
 8780     # check that stop(1) was called
 8781     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-with-no-inout: 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-copy-byte-to-with-no-source:
 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 x/eax: (addr byte) <- copy 0\n")
 8807     (write _test-input-stream "  copy-byte-to *x\n")
 8808     (write _test-input-stream "}\n")
 8809     # convert
 8810     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8811     # registers except esp clobbered at this point
 8812     # restore ed
 8813     89/<- %edx 4/r32/esp
 8814     (flush _test-output-buffered-file)
 8815     (flush _test-error-buffered-file)
 8816 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8822     # check output
 8823     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-to-with-no-source: output should be empty")
 8824     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-byte-to' must have two inouts"  "F - test-copy-byte-to-with-no-source: error message")
 8825     # check that stop(1) was called
 8826     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-with-no-source: exit status")
 8827     # don't restore from ebp
 8828     81 0/subop/add %esp 8/imm32
 8829     # . epilogue
 8830     5d/pop-to-ebp
 8831     c3/return
 8832 
 8833 test-copy-byte-to-with-too-many-inouts:
 8834     # . prologue
 8835     55/push-ebp
 8836     89/<- %ebp 4/r32/esp
 8837     # setup
 8838     (clear-stream _test-input-stream)
 8839     (clear-stream $_test-input-buffered-file->buffer)
 8840     (clear-stream _test-output-stream)
 8841     (clear-stream $_test-output-buffered-file->buffer)
 8842     (clear-stream _test-error-stream)
 8843     (clear-stream $_test-error-buffered-file->buffer)
 8844     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8845     68/push 0/imm32
 8846     68/push 0/imm32
 8847     89/<- %edx 4/r32/esp
 8848     (tailor-exit-descriptor %edx 0x10)
 8849     #
 8850     (write _test-input-stream "fn foo {\n")
 8851     (write _test-input-stream "  var x/eax: (addr byte) <- copy 0\n")
 8852     (write _test-input-stream "  copy-byte-to *x, 0, 0\n")
 8853     (write _test-input-stream "}\n")
 8854     # convert
 8855     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8856     # registers except esp clobbered at this point
 8857     # restore ed
 8858     89/<- %edx 4/r32/esp
 8859     (flush _test-output-buffered-file)
 8860     (flush _test-error-buffered-file)
 8861 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8867     # check output
 8868     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-to-with-too-many-inouts: output should be empty")
 8869     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-byte-to' must have two inouts"  "F - test-copy-byte-to-with-too-many-inouts: error message")
 8870     # check that stop(1) was called
 8871     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-with-too-many-inouts: exit status")
 8872     # don't restore from ebp
 8873     81 0/subop/add %esp 8/imm32
 8874     # . epilogue
 8875     5d/pop-to-ebp
 8876     c3/return
 8877 
 8878 test-copy-byte-to-with-output:
 8879     # . prologue
 8880     55/push-ebp
 8881     89/<- %ebp 4/r32/esp
 8882     # setup
 8883     (clear-stream _test-input-stream)
 8884     (clear-stream $_test-input-buffered-file->buffer)
 8885     (clear-stream _test-output-stream)
 8886     (clear-stream $_test-output-buffered-file->buffer)
 8887     (clear-stream _test-error-stream)
 8888     (clear-stream $_test-error-buffered-file->buffer)
 8889     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8890     68/push 0/imm32
 8891     68/push 0/imm32
 8892     89/<- %edx 4/r32/esp
 8893     (tailor-exit-descriptor %edx 0x10)
 8894     #
 8895     (write _test-input-stream "fn foo {\n")
 8896     (write _test-input-stream "  var x/eax: byte <- copy 0\n")
 8897     (write _test-input-stream "  var y/ecx: (addr byte) <- copy 0\n")
 8898     (write _test-input-stream "  x <- copy-byte-to *y, 0\n")
 8899     (write _test-input-stream "}\n")
 8900     # convert
 8901     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8902     # registers except esp clobbered at this point
 8903     # restore ed
 8904     89/<- %edx 4/r32/esp
 8905     (flush _test-output-buffered-file)
 8906     (flush _test-error-buffered-file)
 8907 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8913     # check output
 8914     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-to-with-output: output should be empty")
 8915     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-byte-to' must not have any outputs"  "F - test-copy-byte-to-with-output: error message")
 8916     # check that stop(1) was called
 8917     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-with-output: exit status")
 8918     # don't restore from ebp
 8919     81 0/subop/add %esp 8/imm32
 8920     # . epilogue
 8921     5d/pop-to-ebp
 8922     c3/return
 8923 
 8924 test-copy-byte-to-with-invalid-output-type:
 8925     # . prologue
 8926     55/push-ebp
 8927     89/<- %ebp 4/r32/esp
 8928     # setup
 8929     (clear-stream _test-input-stream)
 8930     (clear-stream $_test-input-buffered-file->buffer)
 8931     (clear-stream _test-output-stream)
 8932     (clear-stream $_test-output-buffered-file->buffer)
 8933     (clear-stream _test-error-stream)
 8934     (clear-stream $_test-error-buffered-file->buffer)
 8935     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8936     68/push 0/imm32
 8937     68/push 0/imm32
 8938     89/<- %edx 4/r32/esp
 8939     (tailor-exit-descriptor %edx 0x10)
 8940     #
 8941     (write _test-input-stream "fn foo {\n")
 8942     (write _test-input-stream "  var x/eax: byte <- copy 0\n")
 8943     (write _test-input-stream "  var y: int\n")
 8944     (write _test-input-stream "  copy-byte-to y, x\n")
 8945     (write _test-input-stream "}\n")
 8946     # convert
 8947     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8948     # registers except esp clobbered at this point
 8949     # restore ed
 8950     89/<- %edx 4/r32/esp
 8951     (flush _test-output-buffered-file)
 8952     (flush _test-error-buffered-file)
 8953 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8959     # check output
 8960     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-to-with-invalid-output-type: output should be empty")
 8961     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-byte-to: 'y' must be a byte"  "F - test-copy-byte-to-with-invalid-output-type: error message")
 8962     # check that stop(1) was called
 8963     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-with-invalid-output-type: exit status")
 8964     # don't restore from ebp
 8965     81 0/subop/add %esp 8/imm32
 8966     # . epilogue
 8967     5d/pop-to-ebp
 8968     c3/return
 8969 
 8970 test-copy-byte-to-with-literal-inout:
 8971     # . prologue
 8972     55/push-ebp
 8973     89/<- %ebp 4/r32/esp
 8974     # setup
 8975     (clear-stream _test-input-stream)
 8976     (clear-stream $_test-input-buffered-file->buffer)
 8977     (clear-stream _test-output-stream)
 8978     (clear-stream $_test-output-buffered-file->buffer)
 8979     (clear-stream _test-error-stream)
 8980     (clear-stream $_test-error-buffered-file->buffer)
 8981     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8982     68/push 0/imm32
 8983     68/push 0/imm32
 8984     89/<- %edx 4/r32/esp
 8985     (tailor-exit-descriptor %edx 0x10)
 8986     #
 8987     (write _test-input-stream "fn foo {\n")
 8988     (write _test-input-stream "  var x/eax: (addr byte) <- copy 0\n")
 8989     (write _test-input-stream "  copy-byte-to *x, 0\n")
 8990     (write _test-input-stream "}\n")
 8991     # convert
 8992     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8993     # registers except esp clobbered at this point
 8994     # restore ed
 8995     89/<- %edx 4/r32/esp
 8996     (flush _test-output-buffered-file)
 8997     (flush _test-error-buffered-file)
 8998 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9004     # check output
 9005     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-to-with-literal-inout: output should be empty")
 9006     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-byte-to: source (second inout) must be in a register"  "F - test-copy-byte-to-with-literal-inout: error message")
 9007     # check that stop(1) was called
 9008     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-with-literal-inout: exit status")
 9009     # don't restore from ebp
 9010     81 0/subop/add %esp 8/imm32
 9011     # . epilogue
 9012     5d/pop-to-ebp
 9013     c3/return
 9014 
 9015 test-copy-byte-to-deref-address:
 9016     # . prologue
 9017     55/push-ebp
 9018     89/<- %ebp 4/r32/esp
 9019     # setup
 9020     (clear-stream _test-input-stream)
 9021     (clear-stream $_test-input-buffered-file->buffer)
 9022     (clear-stream _test-output-stream)
 9023     (clear-stream $_test-output-buffered-file->buffer)
 9024     #
 9025     (write _test-input-stream "fn foo {\n")
 9026     (write _test-input-stream "  var x/eax: byte <- copy 0\n")
 9027     (write _test-input-stream "  var y/ecx: (addr byte) <- copy 0\n")
 9028     (write _test-input-stream "  copy-byte-to *y, x\n")
 9029     (write _test-input-stream "}\n")
 9030     # convert
 9031     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 9032     (flush _test-output-buffered-file)
 9033     # no errors
 9034     # . epilogue
 9035     5d/pop-to-ebp
 9036     c3/return
 9037 
 9038 test-copy-byte-to-from-non-scalar-inout:
 9039     # . prologue
 9040     55/push-ebp
 9041     89/<- %ebp 4/r32/esp
 9042     # setup
 9043     (clear-stream _test-input-stream)
 9044     (clear-stream $_test-input-buffered-file->buffer)
 9045     (clear-stream _test-output-stream)
 9046     (clear-stream $_test-output-buffered-file->buffer)
 9047     (clear-stream _test-error-stream)
 9048     (clear-stream $_test-error-buffered-file->buffer)
 9049     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9050     68/push 0/imm32
 9051     68/push 0/imm32
 9052     89/<- %edx 4/r32/esp
 9053     (tailor-exit-descriptor %edx 0x10)
 9054     #
 9055     (write _test-input-stream "fn foo {\n")
 9056     (write _test-input-stream "  var x: (handle int)\n")
 9057     (write _test-input-stream "  var y/eax: (addr byte) <- copy 0\n")
 9058     (write _test-input-stream "  copy-byte-to *y, x\n")
 9059     (write _test-input-stream "}\n")
 9060     # convert
 9061     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9062     # registers except esp clobbered at this point
 9063     # restore ed
 9064     89/<- %edx 4/r32/esp
 9065     (flush _test-output-buffered-file)
 9066     (flush _test-error-buffered-file)
 9067 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9073     # check output
 9074     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-to-from-non-scalar-inout: output should be empty")
 9075     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-byte-to: 'x' is too large to copy"  "F - test-copy-byte-to-from-non-scalar-inout: error message")
 9076     # check that stop(1) was called
 9077     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-from-non-scalar-inout: exit status")
 9078     # don't restore from ebp
 9079     81 0/subop/add %esp 8/imm32
 9080     # . epilogue
 9081     5d/pop-to-ebp
 9082     c3/return
 9083 
 9084 test-compare-with-no-inout:
 9085     # . prologue
 9086     55/push-ebp
 9087     89/<- %ebp 4/r32/esp
 9088     # setup
 9089     (clear-stream _test-input-stream)
 9090     (clear-stream $_test-input-buffered-file->buffer)
 9091     (clear-stream _test-output-stream)
 9092     (clear-stream $_test-output-buffered-file->buffer)
 9093     (clear-stream _test-error-stream)
 9094     (clear-stream $_test-error-buffered-file->buffer)
 9095     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9096     68/push 0/imm32
 9097     68/push 0/imm32
 9098     89/<- %edx 4/r32/esp
 9099     (tailor-exit-descriptor %edx 0x10)
 9100     #
 9101     (write _test-input-stream "fn foo {\n")
 9102     (write _test-input-stream "  var x: boolean\n")
 9103     (write _test-input-stream "  compare\n")
 9104     (write _test-input-stream "}\n")
 9105     # convert
 9106     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9107     # registers except esp clobbered at this point
 9108     # restore ed
 9109     89/<- %edx 4/r32/esp
 9110     (flush _test-output-buffered-file)
 9111     (flush _test-error-buffered-file)
 9112 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9118     # check output
 9119     (check-stream-equal _test-output-stream  ""  "F - test-compare-with-no-inout: output should be empty")
 9120     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'compare' must have two inouts"  "F - test-compare-with-no-inout: error message")
 9121     # check that stop(1) was called
 9122     (check-ints-equal *(edx+4) 2 "F - test-compare-with-no-inout: exit status")
 9123     # don't restore from ebp
 9124     81 0/subop/add %esp 8/imm32
 9125     # . epilogue
 9126     5d/pop-to-ebp
 9127     c3/return
 9128 
 9129 test-compare-with-just-one-inout:
 9130     # . prologue
 9131     55/push-ebp
 9132     89/<- %ebp 4/r32/esp
 9133     # setup
 9134     (clear-stream _test-input-stream)
 9135     (clear-stream $_test-input-buffered-file->buffer)
 9136     (clear-stream _test-output-stream)
 9137     (clear-stream $_test-output-buffered-file->buffer)
 9138     (clear-stream _test-error-stream)
 9139     (clear-stream $_test-error-buffered-file->buffer)
 9140     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9141     68/push 0/imm32
 9142     68/push 0/imm32
 9143     89/<- %edx 4/r32/esp
 9144     (tailor-exit-descriptor %edx 0x10)
 9145     #
 9146     (write _test-input-stream "fn foo {\n")
 9147     (write _test-input-stream "  var x: boolean\n")
 9148     (write _test-input-stream "  compare x\n")
 9149     (write _test-input-stream "}\n")
 9150     # convert
 9151     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9152     # registers except esp clobbered at this point
 9153     # restore ed
 9154     89/<- %edx 4/r32/esp
 9155     (flush _test-output-buffered-file)
 9156     (flush _test-error-buffered-file)
 9157 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9163     # check output
 9164     (check-stream-equal _test-output-stream  ""  "F - test-compare-with-just-one-inout: output should be empty")
 9165     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'compare' must have two inouts"  "F - test-compare-with-just-one-inout: error message")
 9166     # check that stop(1) was called
 9167     (check-ints-equal *(edx+4) 2 "F - test-compare-with-just-one-inout: exit status")
 9168     # don't restore from ebp
 9169     81 0/subop/add %esp 8/imm32
 9170     # . epilogue
 9171     5d/pop-to-ebp
 9172     c3/return
 9173 
 9174 test-compare-with-too-many-inouts:
 9175     # . prologue
 9176     55/push-ebp
 9177     89/<- %ebp 4/r32/esp
 9178     # setup
 9179     (clear-stream _test-input-stream)
 9180     (clear-stream $_test-input-buffered-file->buffer)
 9181     (clear-stream _test-output-stream)
 9182     (clear-stream $_test-output-buffered-file->buffer)
 9183     (clear-stream _test-error-stream)
 9184     (clear-stream $_test-error-buffered-file->buffer)
 9185     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9186     68/push 0/imm32
 9187     68/push 0/imm32
 9188     89/<- %edx 4/r32/esp
 9189     (tailor-exit-descriptor %edx 0x10)
 9190     #
 9191     (write _test-input-stream "fn foo {\n")
 9192     (write _test-input-stream "  var x: boolean\n")
 9193     (write _test-input-stream "  compare x, 0, 0\n")
 9194     (write _test-input-stream "}\n")
 9195     # convert
 9196     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9197     # registers except esp clobbered at this point
 9198     # restore ed
 9199     89/<- %edx 4/r32/esp
 9200     (flush _test-output-buffered-file)
 9201     (flush _test-error-buffered-file)
 9202 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9208     # check output
 9209     (check-stream-equal _test-output-stream  ""  "F - test-compare-with-too-many-inouts: output should be empty")
 9210     (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")
 9211     # check that stop(1) was called
 9212     (check-ints-equal *(edx+4) 2 "F - test-compare-with-too-many-inouts: exit status")
 9213     # don't restore from ebp
 9214     81 0/subop/add %esp 8/imm32
 9215     # . epilogue
 9216     5d/pop-to-ebp
 9217     c3/return
 9218 
 9219 test-compare-with-output:
 9220     # . prologue
 9221     55/push-ebp
 9222     89/<- %ebp 4/r32/esp
 9223     # setup
 9224     (clear-stream _test-input-stream)
 9225     (clear-stream $_test-input-buffered-file->buffer)
 9226     (clear-stream _test-output-stream)
 9227     (clear-stream $_test-output-buffered-file->buffer)
 9228     (clear-stream _test-error-stream)
 9229     (clear-stream $_test-error-buffered-file->buffer)
 9230     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9231     68/push 0/imm32
 9232     68/push 0/imm32
 9233     89/<- %edx 4/r32/esp
 9234     (tailor-exit-descriptor %edx 0x10)
 9235     #
 9236     (write _test-input-stream "fn foo {\n")
 9237     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
 9238     (write _test-input-stream "  var y/ecx: boolean <- copy 0\n")
 9239     (write _test-input-stream "  x <- compare y, 0\n")
 9240     (write _test-input-stream "}\n")
 9241     # convert
 9242     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9243     # registers except esp clobbered at this point
 9244     # restore ed
 9245     89/<- %edx 4/r32/esp
 9246     (flush _test-output-buffered-file)
 9247     (flush _test-error-buffered-file)
 9248 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9254     # check output
 9255     (check-stream-equal _test-output-stream  ""  "F - test-compare-with-output: output should be empty")
 9256     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'compare' must not have any outputs"  "F - test-compare-with-output: error message")
 9257     # check that stop(1) was called
 9258     (check-ints-equal *(edx+4) 2 "F - test-compare-with-output: exit status")
 9259     # don't restore from ebp
 9260     81 0/subop/add %esp 8/imm32
 9261     # . epilogue
 9262     5d/pop-to-ebp
 9263     c3/return
 9264 
 9265 test-compare-invalid-value-to-address:
 9266     # . prologue
 9267     55/push-ebp
 9268     89/<- %ebp 4/r32/esp
 9269     # setup
 9270     (clear-stream _test-input-stream)
 9271     (clear-stream $_test-input-buffered-file->buffer)
 9272     (clear-stream _test-output-stream)
 9273     (clear-stream $_test-output-buffered-file->buffer)
 9274     (clear-stream _test-error-stream)
 9275     (clear-stream $_test-error-buffered-file->buffer)
 9276     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9277     68/push 0/imm32
 9278     68/push 0/imm32
 9279     89/<- %edx 4/r32/esp
 9280     (tailor-exit-descriptor %edx 0x10)
 9281     #
 9282     (write _test-input-stream "fn foo {\n")
 9283     (write _test-input-stream "  var x/eax: int <- copy 0\n")
 9284     (write _test-input-stream "  var y: (addr int)\n")
 9285     (write _test-input-stream "  compare y, x\n")
 9286     (write _test-input-stream "}\n")
 9287     # convert
 9288     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9289     # registers except esp clobbered at this point
 9290     # restore ed
 9291     89/<- %edx 4/r32/esp
 9292     (flush _test-output-buffered-file)
 9293     (flush _test-error-buffered-file)
 9294 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9300     # check output
 9301     (check-stream-equal _test-output-stream  ""  "F - test-compare-invalid-value-to-address: output should be empty")
 9302     (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")
 9303     # check that stop(1) was called
 9304     (check-ints-equal *(edx+4) 2 "F - test-compare-invalid-value-to-address: exit status")
 9305     # don't restore from ebp
 9306     81 0/subop/add %esp 8/imm32
 9307     # . epilogue
 9308     5d/pop-to-ebp
 9309     c3/return
 9310 
 9311 test-compare-address:
 9312     # . prologue
 9313     55/push-ebp
 9314     89/<- %ebp 4/r32/esp
 9315     # setup
 9316     (clear-stream _test-input-stream)
 9317     (clear-stream $_test-input-buffered-file->buffer)
 9318     (clear-stream _test-output-stream)
 9319     (clear-stream $_test-output-buffered-file->buffer)
 9320     #
 9321     (write _test-input-stream "fn foo {\n")
 9322     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
 9323     (write _test-input-stream "  var y/ecx: (addr int) <- copy 0\n")
 9324     (write _test-input-stream "  compare y, x\n")
 9325     (write _test-input-stream "}\n")
 9326     # convert
 9327     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 9328     (flush _test-output-buffered-file)
 9329     # no errors
 9330     # . epilogue
 9331     5d/pop-to-ebp
 9332     c3/return
 9333 
 9334 test-compare-deref-address:
 9335     # . prologue
 9336     55/push-ebp
 9337     89/<- %ebp 4/r32/esp
 9338     # setup
 9339     (clear-stream _test-input-stream)
 9340     (clear-stream $_test-input-buffered-file->buffer)
 9341     (clear-stream _test-output-stream)
 9342     (clear-stream $_test-output-buffered-file->buffer)
 9343     #
 9344     (write _test-input-stream "fn foo {\n")
 9345     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
 9346     (write _test-input-stream "  var y/ecx: (addr addr int) <- copy 0\n")
 9347     (write _test-input-stream "  compare *y, x\n")
 9348     (write _test-input-stream "}\n")
 9349     # convert
 9350     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 9351     (flush _test-output-buffered-file)
 9352     # no errors
 9353     # . epilogue
 9354     5d/pop-to-ebp
 9355     c3/return
 9356 
 9357 test-compare-two-vars-in-memory:
 9358     # . prologue
 9359     55/push-ebp
 9360     89/<- %ebp 4/r32/esp
 9361     # setup
 9362     (clear-stream _test-input-stream)
 9363     (clear-stream $_test-input-buffered-file->buffer)
 9364     (clear-stream _test-output-stream)
 9365     (clear-stream $_test-output-buffered-file->buffer)
 9366     (clear-stream _test-error-stream)
 9367     (clear-stream $_test-error-buffered-file->buffer)
 9368     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9369     68/push 0/imm32
 9370     68/push 0/imm32
 9371     89/<- %edx 4/r32/esp
 9372     (tailor-exit-descriptor %edx 0x10)
 9373     #
 9374     (write _test-input-stream "fn foo {\n")
 9375     (write _test-input-stream "  var x: boolean\n")
 9376     (write _test-input-stream "  compare x, x\n")
 9377     (write _test-input-stream "}\n")
 9378     # convert
 9379     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9380     # registers except esp clobbered at this point
 9381     # restore ed
 9382     89/<- %edx 4/r32/esp
 9383     (flush _test-output-buffered-file)
 9384     (flush _test-error-buffered-file)
 9385 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9391     # check output
 9392     (check-stream-equal _test-output-stream  ""  "F - test-compare-two-vars-in-memory: output should be empty")
 9393     (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")
 9394     # check that stop(1) was called
 9395     (check-ints-equal *(edx+4) 2 "F - test-compare-two-vars-in-memory: exit status")
 9396     # don't restore from ebp
 9397     81 0/subop/add %esp 8/imm32
 9398     # . epilogue
 9399     5d/pop-to-ebp
 9400     c3/return
 9401 
 9402 test-compare-non-scalar:
 9403     # . prologue
 9404     55/push-ebp
 9405     89/<- %ebp 4/r32/esp
 9406     # setup
 9407     (clear-stream _test-input-stream)
 9408     (clear-stream $_test-input-buffered-file->buffer)
 9409     (clear-stream _test-output-stream)
 9410     (clear-stream $_test-output-buffered-file->buffer)
 9411     (clear-stream _test-error-stream)
 9412     (clear-stream $_test-error-buffered-file->buffer)
 9413     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9414     68/push 0/imm32
 9415     68/push 0/imm32
 9416     89/<- %edx 4/r32/esp
 9417     (tailor-exit-descriptor %edx 0x10)
 9418     #
 9419     (write _test-input-stream "fn foo {\n")
 9420     (write _test-input-stream "  var x: (handle int)\n")
 9421     (write _test-input-stream "  var y: int\n")
 9422     (write _test-input-stream "  compare y, x\n")
 9423     (write _test-input-stream "}\n")
 9424     # convert
 9425     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9426     # registers except esp clobbered at this point
 9427     # restore ed
 9428     89/<- %edx 4/r32/esp
 9429     (flush _test-output-buffered-file)
 9430     (flush _test-error-buffered-file)
 9431 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9437     # check output
 9438     (check-stream-equal _test-output-stream  ""  "F - test-compare-non-scalar: output should be empty")
 9439 #?     (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")
 9440     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compare: both inouts are in memory"  "F - test-compare-non-scalar: error message")
 9441     # check that stop(1) was called
 9442     (check-ints-equal *(edx+4) 2 "F - test-compare-non-scalar: exit status")
 9443     # don't restore from ebp
 9444     81 0/subop/add %esp 8/imm32
 9445     # . epilogue
 9446     5d/pop-to-ebp
 9447     c3/return
 9448 
 9449 test-address-with-no-inout:
 9450     # . prologue
 9451     55/push-ebp
 9452     89/<- %ebp 4/r32/esp
 9453     # setup
 9454     (clear-stream _test-input-stream)
 9455     (clear-stream $_test-input-buffered-file->buffer)
 9456     (clear-stream _test-output-stream)
 9457     (clear-stream $_test-output-buffered-file->buffer)
 9458     (clear-stream _test-error-stream)
 9459     (clear-stream $_test-error-buffered-file->buffer)
 9460     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9461     68/push 0/imm32
 9462     68/push 0/imm32
 9463     89/<- %edx 4/r32/esp
 9464     (tailor-exit-descriptor %edx 0x10)
 9465     #
 9466     (write _test-input-stream "fn foo {\n")
 9467     (write _test-input-stream "  var x/eax: boolean <- address\n")
 9468     (write _test-input-stream "}\n")
 9469     # convert
 9470     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9471     # registers except esp clobbered at this point
 9472     # restore ed
 9473     89/<- %edx 4/r32/esp
 9474     (flush _test-output-buffered-file)
 9475     (flush _test-error-buffered-file)
 9476 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9482     # check output
 9483     (check-stream-equal _test-output-stream  ""  "F - test-address-with-no-inout: output should be empty")
 9484     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'address' expects an inout"  "F - test-address-with-no-inout: error message")
 9485     # check that stop(1) was called
 9486     (check-ints-equal *(edx+4) 2 "F - test-address-with-no-inout: exit status")
 9487     # don't restore from ebp
 9488     81 0/subop/add %esp 8/imm32
 9489     # . epilogue
 9490     5d/pop-to-ebp
 9491     c3/return
 9492 
 9493 test-address-with-multiple-inouts:
 9494     # . prologue
 9495     55/push-ebp
 9496     89/<- %ebp 4/r32/esp
 9497     # setup
 9498     (clear-stream _test-input-stream)
 9499     (clear-stream $_test-input-buffered-file->buffer)
 9500     (clear-stream _test-output-stream)
 9501     (clear-stream $_test-output-buffered-file->buffer)
 9502     (clear-stream _test-error-stream)
 9503     (clear-stream $_test-error-buffered-file->buffer)
 9504     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9505     68/push 0/imm32
 9506     68/push 0/imm32
 9507     89/<- %edx 4/r32/esp
 9508     (tailor-exit-descriptor %edx 0x10)
 9509     #
 9510     (write _test-input-stream "fn foo {\n")
 9511     (write _test-input-stream "  var x/eax: boolean <- address 0, 0\n")
 9512     (write _test-input-stream "}\n")
 9513     # convert
 9514     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9515     # registers except esp clobbered at this point
 9516     # restore ed
 9517     89/<- %edx 4/r32/esp
 9518     (flush _test-output-buffered-file)
 9519     (flush _test-error-buffered-file)
 9520 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9526     # check output
 9527     (check-stream-equal _test-output-stream  ""  "F - test-address-with-multiple-inouts: output should be empty")
 9528     (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")
 9529     # check that stop(1) was called
 9530     (check-ints-equal *(edx+4) 2 "F - test-address-with-multiple-inouts: exit status")
 9531     # don't restore from ebp
 9532     81 0/subop/add %esp 8/imm32
 9533     # . epilogue
 9534     5d/pop-to-ebp
 9535     c3/return
 9536 
 9537 test-address-with-no-output:
 9538     # . prologue
 9539     55/push-ebp
 9540     89/<- %ebp 4/r32/esp
 9541     # setup
 9542     (clear-stream _test-input-stream)
 9543     (clear-stream $_test-input-buffered-file->buffer)
 9544     (clear-stream _test-output-stream)
 9545     (clear-stream $_test-output-buffered-file->buffer)
 9546     (clear-stream _test-error-stream)
 9547     (clear-stream $_test-error-buffered-file->buffer)
 9548     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9549     68/push 0/imm32
 9550     68/push 0/imm32
 9551     89/<- %edx 4/r32/esp
 9552     (tailor-exit-descriptor %edx 0x10)
 9553     #
 9554     (write _test-input-stream "fn foo {\n")
 9555     (write _test-input-stream "  address 0\n")
 9556     (write _test-input-stream "}\n")
 9557     # convert
 9558     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9559     # registers except esp clobbered at this point
 9560     # restore ed
 9561     89/<- %edx 4/r32/esp
 9562     (flush _test-output-buffered-file)
 9563     (flush _test-error-buffered-file)
 9564 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9570     # check output
 9571     (check-stream-equal _test-output-stream  ""  "F - test-address-with-no-output: output should be empty")
 9572     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'address' expects an output"  "F - test-address-with-no-output: error message")
 9573     # check that stop(1) was called
 9574     (check-ints-equal *(edx+4) 2 "F - test-address-with-no-output: exit status")
 9575     # don't restore from ebp
 9576     81 0/subop/add %esp 8/imm32
 9577     # . epilogue
 9578     5d/pop-to-ebp
 9579     c3/return
 9580 
 9581 test-address-with-multiple-outputs:
 9582     # . prologue
 9583     55/push-ebp
 9584     89/<- %ebp 4/r32/esp
 9585     # setup
 9586     (clear-stream _test-input-stream)
 9587     (clear-stream $_test-input-buffered-file->buffer)
 9588     (clear-stream _test-output-stream)
 9589     (clear-stream $_test-output-buffered-file->buffer)
 9590     (clear-stream _test-error-stream)
 9591     (clear-stream $_test-error-buffered-file->buffer)
 9592     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9593     68/push 0/imm32
 9594     68/push 0/imm32
 9595     89/<- %edx 4/r32/esp
 9596     (tailor-exit-descriptor %edx 0x10)
 9597     #
 9598     (write _test-input-stream "fn foo {\n")
 9599     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
 9600     (write _test-input-stream "  var y/ecx: boolean <- copy 0\n")
 9601     (write _test-input-stream "  x, y <- address 0\n")
 9602     (write _test-input-stream "}\n")
 9603     # convert
 9604     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9605     # registers except esp clobbered at this point
 9606     # restore ed
 9607     89/<- %edx 4/r32/esp
 9608     (flush _test-output-buffered-file)
 9609     (flush _test-error-buffered-file)
 9610 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9616     # check output
 9617     (check-stream-equal _test-output-stream  ""  "F - test-address-with-multiple-outputs: output should be empty")
 9618     (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")
 9619     # check that stop(1) was called
 9620     (check-ints-equal *(edx+4) 2 "F - test-address-with-multiple-outputs: exit status")
 9621     # don't restore from ebp
 9622     81 0/subop/add %esp 8/imm32
 9623     # . epilogue
 9624     5d/pop-to-ebp
 9625     c3/return
 9626 
 9627 # silly but it works
 9628 test-address-of-deref:
 9629     # . prologue
 9630     55/push-ebp
 9631     89/<- %ebp 4/r32/esp
 9632     # setup
 9633     (clear-stream _test-input-stream)
 9634     (clear-stream $_test-input-buffered-file->buffer)
 9635     (clear-stream _test-output-stream)
 9636     (clear-stream $_test-output-buffered-file->buffer)
 9637     #
 9638     (write _test-input-stream "fn foo {\n")
 9639     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
 9640     (write _test-input-stream "  var y/ecx: (addr int) <- address *x\n")
 9641     (write _test-input-stream "}\n")
 9642     # convert
 9643     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 9644     (flush _test-output-buffered-file)
 9645     # no errors
 9646     # . epilogue
 9647     5d/pop-to-ebp
 9648     c3/return
 9649 
 9650 test-address-to-non-register:
 9651     # . prologue
 9652     55/push-ebp
 9653     89/<- %ebp 4/r32/esp
 9654     # setup
 9655     (clear-stream _test-input-stream)
 9656     (clear-stream $_test-input-buffered-file->buffer)
 9657     (clear-stream _test-output-stream)
 9658     (clear-stream $_test-output-buffered-file->buffer)
 9659     (clear-stream _test-error-stream)
 9660     (clear-stream $_test-error-buffered-file->buffer)
 9661     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9662     68/push 0/imm32
 9663     68/push 0/imm32
 9664     89/<- %edx 4/r32/esp
 9665     (tailor-exit-descriptor %edx 0x10)
 9666     #
 9667     (write _test-input-stream "fn foo {\n")
 9668     (write _test-input-stream "  var x: (addr int)\n")
 9669     (write _test-input-stream "  x <- address 0\n")
 9670     (write _test-input-stream "}\n")
 9671     # convert
 9672     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9673     # registers except esp clobbered at this point
 9674     # restore ed
 9675     89/<- %edx 4/r32/esp
 9676     (flush _test-output-buffered-file)
 9677     (flush _test-error-buffered-file)
 9678 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9684     # check output
 9685     (check-stream-equal _test-output-stream  ""  "F - test-address-to-non-register: output should be empty")
 9686     (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")
 9687     # check that stop(1) was called
 9688     (check-ints-equal *(edx+4) 2 "F - test-address-to-non-register: exit status")
 9689     # don't restore from ebp
 9690     81 0/subop/add %esp 8/imm32
 9691     # . epilogue
 9692     5d/pop-to-ebp
 9693     c3/return
 9694 
 9695 test-address-with-wrong-type:
 9696     # . prologue
 9697     55/push-ebp
 9698     89/<- %ebp 4/r32/esp
 9699     # setup
 9700     (clear-stream _test-input-stream)
 9701     (clear-stream $_test-input-buffered-file->buffer)
 9702     (clear-stream _test-output-stream)
 9703     (clear-stream $_test-output-buffered-file->buffer)
 9704     (clear-stream _test-error-stream)
 9705     (clear-stream $_test-error-buffered-file->buffer)
 9706     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9707     68/push 0/imm32
 9708     68/push 0/imm32
 9709     89/<- %edx 4/r32/esp
 9710     (tailor-exit-descriptor %edx 0x10)
 9711     #
 9712     (write _test-input-stream "fn foo {\n")
 9713     (write _test-input-stream "  var x: int\n")
 9714     (write _test-input-stream "  var y/eax: (addr boolean) <- address x\n")
 9715     (write _test-input-stream "}\n")
 9716     # convert
 9717     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9718     # registers except esp clobbered at this point
 9719     # restore ed
 9720     89/<- %edx 4/r32/esp
 9721     (flush _test-output-buffered-file)
 9722     (flush _test-error-buffered-file)
 9723 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9729     # check output
 9730     (check-stream-equal _test-output-stream  ""  "F - test-address-with-wrong-type: output should be empty")
 9731     (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")
 9732     # check that stop(1) was called
 9733     (check-ints-equal *(edx+4) 2 "F - test-address-with-wrong-type: exit status")
 9734     # don't restore from ebp
 9735     81 0/subop/add %esp 8/imm32
 9736     # . epilogue
 9737     5d/pop-to-ebp
 9738     c3/return
 9739 
 9740 test-address-with-right-type-for-array:
 9741     # . prologue
 9742     55/push-ebp
 9743     89/<- %ebp 4/r32/esp
 9744     # setup
 9745     (clear-stream _test-input-stream)
 9746     (clear-stream $_test-input-buffered-file->buffer)
 9747     (clear-stream _test-output-stream)
 9748     (clear-stream $_test-output-buffered-file->buffer)
 9749     #
 9750     (write _test-input-stream "fn foo {\n")
 9751     (write _test-input-stream "  var x: (array int 3)\n")
 9752     (write _test-input-stream "  var y/eax: (addr array int) <- address x\n")
 9753     (write _test-input-stream "}\n")
 9754     # convert
 9755     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 9756     (flush _test-output-buffered-file)
 9757     # no errors
 9758     # . epilogue
 9759     89/<- %esp 5/r32/ebp
 9760     5d/pop-to-ebp
 9761     c3/return
 9762 
 9763 test-address-with-right-type-for-stream:
 9764     # . prologue
 9765     55/push-ebp
 9766     89/<- %ebp 4/r32/esp
 9767     # setup
 9768     (clear-stream _test-input-stream)
 9769     (clear-stream $_test-input-buffered-file->buffer)
 9770     (clear-stream _test-output-stream)
 9771     (clear-stream $_test-output-buffered-file->buffer)
 9772     #
 9773     (write _test-input-stream "fn foo {\n")
 9774     (write _test-input-stream "  var x: (stream int 3)\n")
 9775     (write _test-input-stream "  var y/eax: (addr stream int) <- address x\n")
 9776     (write _test-input-stream "}\n")
 9777     # convert
 9778     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 9779     (flush _test-output-buffered-file)
 9780     # no errors
 9781     # . epilogue
 9782     89/<- %esp 5/r32/ebp
 9783     5d/pop-to-ebp
 9784     c3/return
 9785 
 9786 test-get-with-wrong-field:
 9787     # . prologue
 9788     55/push-ebp
 9789     89/<- %ebp 4/r32/esp
 9790     # setup
 9791     (clear-stream _test-input-stream)
 9792     (clear-stream $_test-input-buffered-file->buffer)
 9793     (clear-stream _test-output-stream)
 9794     (clear-stream $_test-output-buffered-file->buffer)
 9795     (clear-stream _test-error-stream)
 9796     (clear-stream $_test-error-buffered-file->buffer)
 9797     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9798     68/push 0/imm32
 9799     68/push 0/imm32
 9800     89/<- %edx 4/r32/esp
 9801     (tailor-exit-descriptor %edx 0x10)
 9802     #
 9803     (write _test-input-stream "fn foo {\n")
 9804     (write _test-input-stream "  var a: t\n")
 9805     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 9806     (write _test-input-stream "}\n")
 9807     (write _test-input-stream "type t {\n")
 9808     (write _test-input-stream "  x: int\n")
 9809     (write _test-input-stream "}\n")
 9810     # convert
 9811     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9812     # registers except esp clobbered at this point
 9813     # restore ed
 9814     89/<- %edx 4/r32/esp
 9815     (flush _test-output-buffered-file)
 9816     (flush _test-error-buffered-file)
 9817 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9823     # check output
 9824     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-field: output should be empty")
 9825     (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")
 9826     # check that stop(1) was called
 9827     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-field: exit status")
 9828     # don't restore from ebp
 9829     81 0/subop/add %esp 8/imm32
 9830     # . epilogue
 9831     5d/pop-to-ebp
 9832     c3/return
 9833 
 9834 test-get-with-wrong-base-type:
 9835     # . prologue
 9836     55/push-ebp
 9837     89/<- %ebp 4/r32/esp
 9838     # setup
 9839     (clear-stream _test-input-stream)
 9840     (clear-stream $_test-input-buffered-file->buffer)
 9841     (clear-stream _test-output-stream)
 9842     (clear-stream $_test-output-buffered-file->buffer)
 9843     (clear-stream _test-error-stream)
 9844     (clear-stream $_test-error-buffered-file->buffer)
 9845     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9846     68/push 0/imm32
 9847     68/push 0/imm32
 9848     89/<- %edx 4/r32/esp
 9849     (tailor-exit-descriptor %edx 0x10)
 9850     #
 9851     (write _test-input-stream "fn foo {\n")
 9852     (write _test-input-stream "  var a: int\n")
 9853     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 9854     (write _test-input-stream "}\n")
 9855     # convert
 9856     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9857     # registers except esp clobbered at this point
 9858     # restore ed
 9859     89/<- %edx 4/r32/esp
 9860     (flush _test-output-buffered-file)
 9861     (flush _test-error-buffered-file)
 9862 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9868     # check output
 9869     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-base-type: output should be empty")
 9870     (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")
 9871     # check that stop(1) was called
 9872     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-base-type: exit status")
 9873     # don't restore from ebp
 9874     81 0/subop/add %esp 8/imm32
 9875     # . epilogue
 9876     5d/pop-to-ebp
 9877     c3/return
 9878 
 9879 test-get-with-wrong-base-type-2:
 9880     # . prologue
 9881     55/push-ebp
 9882     89/<- %ebp 4/r32/esp
 9883     # setup
 9884     (clear-stream _test-input-stream)
 9885     (clear-stream $_test-input-buffered-file->buffer)
 9886     (clear-stream _test-output-stream)
 9887     (clear-stream $_test-output-buffered-file->buffer)
 9888     (clear-stream _test-error-stream)
 9889     (clear-stream $_test-error-buffered-file->buffer)
 9890     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9891     68/push 0/imm32
 9892     68/push 0/imm32
 9893     89/<- %edx 4/r32/esp
 9894     (tailor-exit-descriptor %edx 0x10)
 9895     #
 9896     (write _test-input-stream "fn foo {\n")
 9897     (write _test-input-stream "  var a: (addr t)\n")
 9898     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 9899     (write _test-input-stream "}\n")
 9900     (write _test-input-stream "type t {\n")
 9901     (write _test-input-stream "  x: int\n")
 9902     (write _test-input-stream "}\n")
 9903     # convert
 9904     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9905     # registers except esp clobbered at this point
 9906     # restore ed
 9907     89/<- %edx 4/r32/esp
 9908     (flush _test-output-buffered-file)
 9909     (flush _test-error-buffered-file)
 9910 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9916     # check output
 9917     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-base-type-2: output should be empty")
 9918     (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")
 9919     # check that stop(1) was called
 9920     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-base-type-2: exit status")
 9921     # don't restore from ebp
 9922     81 0/subop/add %esp 8/imm32
 9923     # . epilogue
 9924     5d/pop-to-ebp
 9925     c3/return
 9926 
 9927 test-get-with-wrong-base-type-3:
 9928     # . prologue
 9929     55/push-ebp
 9930     89/<- %ebp 4/r32/esp
 9931     # setup
 9932     (clear-stream _test-input-stream)
 9933     (clear-stream $_test-input-buffered-file->buffer)
 9934     (clear-stream _test-output-stream)
 9935     (clear-stream $_test-output-buffered-file->buffer)
 9936     (clear-stream _test-error-stream)
 9937     (clear-stream $_test-error-buffered-file->buffer)
 9938     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9939     68/push 0/imm32
 9940     68/push 0/imm32
 9941     89/<- %edx 4/r32/esp
 9942     (tailor-exit-descriptor %edx 0x10)
 9943     #
 9944     (write _test-input-stream "fn foo {\n")
 9945     (write _test-input-stream "  var a: (handle int)\n")
 9946     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 9947     (write _test-input-stream "}\n")
 9948     # convert
 9949     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9950     # registers except esp clobbered at this point
 9951     # restore ed
 9952     89/<- %edx 4/r32/esp
 9953     (flush _test-output-buffered-file)
 9954     (flush _test-error-buffered-file)
 9955 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9961     # check output
 9962     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-base-type-3: output should be empty")
 9963     (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")
 9964     # check that stop(1) was called
 9965     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-base-type-3: exit status")
 9966     # don't restore from ebp
 9967     81 0/subop/add %esp 8/imm32
 9968     # . epilogue
 9969     5d/pop-to-ebp
 9970     c3/return
 9971 
 9972 test-get-with-wrong-offset-type:
 9973     # . prologue
 9974     55/push-ebp
 9975     89/<- %ebp 4/r32/esp
 9976     # setup
 9977     (clear-stream _test-input-stream)
 9978     (clear-stream $_test-input-buffered-file->buffer)
 9979     (clear-stream _test-output-stream)
 9980     (clear-stream $_test-output-buffered-file->buffer)
 9981     (clear-stream _test-error-stream)
 9982     (clear-stream $_test-error-buffered-file->buffer)
 9983     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9984     68/push 0/imm32
 9985     68/push 0/imm32
 9986     89/<- %edx 4/r32/esp
 9987     (tailor-exit-descriptor %edx 0x10)
 9988     #
 9989     (write _test-input-stream "fn foo {\n")
 9990     (write _test-input-stream "  var a: t\n")
 9991     (write _test-input-stream "  var b: int\n")
 9992     (write _test-input-stream "  var c/ecx: (addr int) <- get a, b\n")
 9993     (write _test-input-stream "}\n")
 9994     (write _test-input-stream "type t {\n")
 9995     (write _test-input-stream "  x: int\n")
 9996     (write _test-input-stream "}\n")
 9997     # convert
 9998     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9999     # registers except esp clobbered at this point
10000     # restore ed
10001     89/<- %edx 4/r32/esp
10002     (flush _test-output-buffered-file)
10003     (flush _test-error-buffered-file)
10004 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10010     # check output
10011     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-offset-type: output should be empty")
10012     (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")
10013     # check that stop(1) was called
10014     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-offset-type: exit status")
10015     # don't restore from ebp
10016     81 0/subop/add %esp 8/imm32
10017     # . epilogue
10018     5d/pop-to-ebp
10019     c3/return
10020 
10021 test-get-with-wrong-output-type:
10022     # . prologue
10023     55/push-ebp
10024     89/<- %ebp 4/r32/esp
10025     # setup
10026     (clear-stream _test-input-stream)
10027     (clear-stream $_test-input-buffered-file->buffer)
10028     (clear-stream _test-output-stream)
10029     (clear-stream $_test-output-buffered-file->buffer)
10030     (clear-stream _test-error-stream)
10031     (clear-stream $_test-error-buffered-file->buffer)
10032     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10033     68/push 0/imm32
10034     68/push 0/imm32
10035     89/<- %edx 4/r32/esp
10036     (tailor-exit-descriptor %edx 0x10)
10037     #
10038     (write _test-input-stream "fn foo {\n")
10039     (write _test-input-stream "  var a: t\n")
10040     (write _test-input-stream "  var c: (addr int)\n")
10041     (write _test-input-stream "  c <- get a, x\n")
10042     (write _test-input-stream "}\n")
10043     (write _test-input-stream "type t {\n")
10044     (write _test-input-stream "  x: int\n")
10045     (write _test-input-stream "}\n")
10046     # convert
10047     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10048     # registers except esp clobbered at this point
10049     # restore ed
10050     89/<- %edx 4/r32/esp
10051     (flush _test-output-buffered-file)
10052     (flush _test-error-buffered-file)
10053 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10059     # check output
10060     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type: output should be empty")
10061     (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")
10062     # check that stop(1) was called
10063     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type: exit status")
10064     # don't restore from ebp
10065     81 0/subop/add %esp 8/imm32
10066     # . epilogue
10067     5d/pop-to-ebp
10068     c3/return
10069 
10070 test-get-with-wrong-output-type-2:
10071     # . prologue
10072     55/push-ebp
10073     89/<- %ebp 4/r32/esp
10074     # setup
10075     (clear-stream _test-input-stream)
10076     (clear-stream $_test-input-buffered-file->buffer)
10077     (clear-stream _test-output-stream)
10078     (clear-stream $_test-output-buffered-file->buffer)
10079     (clear-stream _test-error-stream)
10080     (clear-stream $_test-error-buffered-file->buffer)
10081     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10082     68/push 0/imm32
10083     68/push 0/imm32
10084     89/<- %edx 4/r32/esp
10085     (tailor-exit-descriptor %edx 0x10)
10086     #
10087     (write _test-input-stream "fn foo {\n")
10088     (write _test-input-stream "  var a: t\n")
10089     (write _test-input-stream "  var c/ecx: int <- get a, x\n")
10090     (write _test-input-stream "}\n")
10091     (write _test-input-stream "type t {\n")
10092     (write _test-input-stream "  x: int\n")
10093     (write _test-input-stream "}\n")
10094     # convert
10095     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10096     # registers except esp clobbered at this point
10097     # restore ed
10098     89/<- %edx 4/r32/esp
10099     (flush _test-output-buffered-file)
10100     (flush _test-error-buffered-file)
10101 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10107     # check output
10108     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type-2: output should be empty")
10109     (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")
10110     # check that stop(1) was called
10111     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type-2: exit status")
10112     # don't restore from ebp
10113     81 0/subop/add %esp 8/imm32
10114     # . epilogue
10115     5d/pop-to-ebp
10116     c3/return
10117 
10118 test-get-with-wrong-output-type-3:
10119     # . prologue
10120     55/push-ebp
10121     89/<- %ebp 4/r32/esp
10122     # setup
10123     (clear-stream _test-input-stream)
10124     (clear-stream $_test-input-buffered-file->buffer)
10125     (clear-stream _test-output-stream)
10126     (clear-stream $_test-output-buffered-file->buffer)
10127     (clear-stream _test-error-stream)
10128     (clear-stream $_test-error-buffered-file->buffer)
10129     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10130     68/push 0/imm32
10131     68/push 0/imm32
10132     89/<- %edx 4/r32/esp
10133     (tailor-exit-descriptor %edx 0x10)
10134     #
10135     (write _test-input-stream "fn foo {\n")
10136     (write _test-input-stream "  var a: t\n")
10137     (write _test-input-stream "  var c/ecx: (array int) <- get a, x\n")
10138     (write _test-input-stream "}\n")
10139     (write _test-input-stream "type t {\n")
10140     (write _test-input-stream "  x: int\n")
10141     (write _test-input-stream "}\n")
10142     # convert
10143     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10144     # registers except esp clobbered at this point
10145     # restore ed
10146     89/<- %edx 4/r32/esp
10147     (flush _test-output-buffered-file)
10148     (flush _test-error-buffered-file)
10149 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10155     # check output
10156     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type-3: output should be empty")
10157     (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")
10158     # check that stop(1) was called
10159     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type-3: exit status")
10160     # don't restore from ebp
10161     81 0/subop/add %esp 8/imm32
10162     # . epilogue
10163     5d/pop-to-ebp
10164     c3/return
10165 
10166 test-get-with-wrong-output-type-4:
10167     # . prologue
10168     55/push-ebp
10169     89/<- %ebp 4/r32/esp
10170     # setup
10171     (clear-stream _test-input-stream)
10172     (clear-stream $_test-input-buffered-file->buffer)
10173     (clear-stream _test-output-stream)
10174     (clear-stream $_test-output-buffered-file->buffer)
10175     (clear-stream _test-error-stream)
10176     (clear-stream $_test-error-buffered-file->buffer)
10177     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10178     68/push 0/imm32
10179     68/push 0/imm32
10180     89/<- %edx 4/r32/esp
10181     (tailor-exit-descriptor %edx 0x10)
10182     #
10183     (write _test-input-stream "fn foo {\n")
10184     (write _test-input-stream "  var a: t\n")
10185     (write _test-input-stream "  var c/ecx: (addr boolean) <- get a, x\n")
10186     (write _test-input-stream "}\n")
10187     (write _test-input-stream "type t {\n")
10188     (write _test-input-stream "  x: int\n")
10189     (write _test-input-stream "}\n")
10190     # convert
10191     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10192     # registers except esp clobbered at this point
10193     # restore ed
10194     89/<- %edx 4/r32/esp
10195     (flush _test-output-buffered-file)
10196     (flush _test-error-buffered-file)
10197 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10203     # check output
10204     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type-4: output should be empty")
10205     (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")
10206     # check that stop(1) was called
10207     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type-4: exit status")
10208     # don't restore from ebp
10209     81 0/subop/add %esp 8/imm32
10210     # . epilogue
10211     5d/pop-to-ebp
10212     c3/return
10213 
10214 test-get-with-wrong-output-type-5:
10215     # . prologue
10216     55/push-ebp
10217     89/<- %ebp 4/r32/esp
10218     # setup
10219     (clear-stream _test-input-stream)
10220     (clear-stream $_test-input-buffered-file->buffer)
10221     (clear-stream _test-output-stream)
10222     (clear-stream $_test-output-buffered-file->buffer)
10223     #
10224     (write _test-input-stream "fn foo {\n")
10225     (write _test-input-stream "  var a: t\n")
10226     (write _test-input-stream "  var c/ecx: (addr handle int) <- get a, x\n")
10227     (write _test-input-stream "}\n")
10228     (write _test-input-stream "type t {\n")
10229     (write _test-input-stream "  x: (handle int)\n")
10230     (write _test-input-stream "}\n")
10231     # convert
10232     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
10233     (flush _test-output-buffered-file)
10234     # no errors
10235     # . epilogue
10236     89/<- %esp 5/r32/ebp
10237     5d/pop-to-ebp
10238     c3/return
10239 
10240 test-get-with-too-few-inouts:
10241     # . prologue
10242     55/push-ebp
10243     89/<- %ebp 4/r32/esp
10244     # setup
10245     (clear-stream _test-input-stream)
10246     (clear-stream $_test-input-buffered-file->buffer)
10247     (clear-stream _test-output-stream)
10248     (clear-stream $_test-output-buffered-file->buffer)
10249     (clear-stream _test-error-stream)
10250     (clear-stream $_test-error-buffered-file->buffer)
10251     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10252     68/push 0/imm32
10253     68/push 0/imm32
10254     89/<- %edx 4/r32/esp
10255     (tailor-exit-descriptor %edx 0x10)
10256     #
10257     (write _test-input-stream "fn foo {\n")
10258     (write _test-input-stream "  var a: t\n")
10259     (write _test-input-stream "  var c/ecx: (addr int) <- get a\n")
10260     (write _test-input-stream "}\n")
10261     (write _test-input-stream "type t {\n")
10262     (write _test-input-stream "  x: int\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-get-with-too-few-inouts: output should be empty")
10279     (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")
10280     # check that stop(1) was called
10281     (check-ints-equal *(edx+4) 2 "F - test-get-with-too-few-inouts: 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-get-with-too-many-inouts:
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: t\n")
10307     (write _test-input-stream "  var c/ecx: (addr int) <- get a, x, 0\n")
10308     (write _test-input-stream "}\n")
10309     (write _test-input-stream "type t {\n")
10310     (write _test-input-stream "  x: int\n")
10311     (write _test-input-stream "}\n")
10312     # convert
10313     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10314     # registers except esp clobbered at this point
10315     # restore ed
10316     89/<- %edx 4/r32/esp
10317     (flush _test-output-buffered-file)
10318     (flush _test-error-buffered-file)
10319 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10325     # check output
10326     (check-stream-equal _test-output-stream  ""  "F - test-get-with-too-many-inouts: output should be empty")
10327     (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")
10328     # check that stop(1) was called
10329     (check-ints-equal *(edx+4) 2 "F - test-get-with-too-many-inouts: exit status")
10330     # don't restore from ebp
10331     81 0/subop/add %esp 8/imm32
10332     # . epilogue
10333     5d/pop-to-ebp
10334     c3/return
10335 
10336 test-get-with-no-output:
10337     # . prologue
10338     55/push-ebp
10339     89/<- %ebp 4/r32/esp
10340     # setup
10341     (clear-stream _test-input-stream)
10342     (clear-stream $_test-input-buffered-file->buffer)
10343     (clear-stream _test-output-stream)
10344     (clear-stream $_test-output-buffered-file->buffer)
10345     (clear-stream _test-error-stream)
10346     (clear-stream $_test-error-buffered-file->buffer)
10347     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10348     68/push 0/imm32
10349     68/push 0/imm32
10350     89/<- %edx 4/r32/esp
10351     (tailor-exit-descriptor %edx 0x10)
10352     #
10353     (write _test-input-stream "fn foo {\n")
10354     (write _test-input-stream "  var a: t\n")
10355     (write _test-input-stream "  get a, x\n")
10356     (write _test-input-stream "}\n")
10357     (write _test-input-stream "type t {\n")
10358     (write _test-input-stream "  x: int\n")
10359     (write _test-input-stream "}\n")
10360     # convert
10361     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10362     # registers except esp clobbered at this point
10363     # restore ed
10364     89/<- %edx 4/r32/esp
10365     (flush _test-output-buffered-file)
10366     (flush _test-error-buffered-file)
10367 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10373     # check output
10374     (check-stream-equal _test-output-stream  ""  "F - test-get-with-no-output: output should be empty")
10375     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt get: must have an output"  "F - test-get-with-no-output: error message")
10376     # check that stop(1) was called
10377     (check-ints-equal *(edx+4) 2 "F - test-get-with-no-output: exit status")
10378     # don't restore from ebp
10379     81 0/subop/add %esp 8/imm32
10380     # . epilogue
10381     5d/pop-to-ebp
10382     c3/return
10383 
10384 test-get-with-too-many-outputs:
10385     # . prologue
10386     55/push-ebp
10387     89/<- %ebp 4/r32/esp
10388     # setup
10389     (clear-stream _test-input-stream)
10390     (clear-stream $_test-input-buffered-file->buffer)
10391     (clear-stream _test-output-stream)
10392     (clear-stream $_test-output-buffered-file->buffer)
10393     (clear-stream _test-error-stream)
10394     (clear-stream $_test-error-buffered-file->buffer)
10395     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10396     68/push 0/imm32
10397     68/push 0/imm32
10398     89/<- %edx 4/r32/esp
10399     (tailor-exit-descriptor %edx 0x10)
10400     #
10401     (write _test-input-stream "fn foo {\n")
10402     (write _test-input-stream "  var a: t\n")
10403     (write _test-input-stream "  var b: int\n")
10404     (write _test-input-stream "  var c/eax: (addr int) <- copy 0\n")
10405     (write _test-input-stream "  c, b <- get a, x\n")
10406     (write _test-input-stream "}\n")
10407     (write _test-input-stream "type t {\n")
10408     (write _test-input-stream "  x: int\n")
10409     (write _test-input-stream "}\n")
10410     # convert
10411     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10412     # registers except esp clobbered at this point
10413     # restore ed
10414     89/<- %edx 4/r32/esp
10415     (flush _test-output-buffered-file)
10416     (flush _test-error-buffered-file)
10417 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10423     # check output
10424     (check-stream-equal _test-output-stream  ""  "F - test-get-with-too-many-outputs: output should be empty")
10425     (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")
10426     # check that stop(1) was called
10427     (check-ints-equal *(edx+4) 2 "F - test-get-with-too-many-outputs: exit status")
10428     # don't restore from ebp
10429     81 0/subop/add %esp 8/imm32
10430     # . epilogue
10431     5d/pop-to-ebp
10432     c3/return
10433 
10434 test-convert-array-of-user-defined-types:
10435     # . prologue
10436     55/push-ebp
10437     89/<- %ebp 4/r32/esp
10438     # setup
10439     (clear-stream _test-input-stream)
10440     (clear-stream $_test-input-buffered-file->buffer)
10441     (clear-stream _test-output-stream)
10442     (clear-stream $_test-output-buffered-file->buffer)
10443     #
10444     (write _test-input-stream "type t {\n")  # each t is 8 bytes, which is a power of 2
10445     (write _test-input-stream "  x: int\n")
10446     (write _test-input-stream "  y: int\n")
10447     (write _test-input-stream "}\n")
10448     (write _test-input-stream "fn foo {\n")
10449     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
10450     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
10451     (write _test-input-stream "  var x/eax: (addr t) <- index arr, idx\n")
10452     (write _test-input-stream "}\n")
10453     # convert
10454     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
10455     (flush _test-output-buffered-file)
10456 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
10462     # check output
10463     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-array-of-user-defined-types/0")
10464     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-array-of-user-defined-types/1")
10465     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-array-of-user-defined-types/2")
10466     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-array-of-user-defined-types/3")
10467     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-array-of-user-defined-types/4")
10468     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-array-of-user-defined-types/5")
10469     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-array-of-user-defined-types/6")
10470     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-array-of-user-defined-types/7")
10471     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-array-of-user-defined-types/8")
10472     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-array-of-user-defined-types/9")
10473     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds %ecx 0x00000008 *eax \"foo\" \"arr\")"  "F - test-convert-array-of-user-defined-types/10")
10474     (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")
10475     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-array-of-user-defined-types/12")
10476     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-array-of-user-defined-types/13")
10477     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-array-of-user-defined-types/14")
10478     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-array-of-user-defined-types/15")
10479     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-array-of-user-defined-types/16")
10480     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-array-of-user-defined-types/17")
10481     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-array-of-user-defined-types/18")
10482     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-array-of-user-defined-types/19")
10483     # . epilogue
10484     89/<- %esp 5/r32/ebp
10485     5d/pop-to-ebp
10486     c3/return
10487 
10488 test-convert-length-of-array-of-user-defined-types-to-eax:
10489     # . prologue
10490     55/push-ebp
10491     89/<- %ebp 4/r32/esp
10492     # setup
10493     (clear-stream _test-input-stream)
10494     (clear-stream $_test-input-buffered-file->buffer)
10495     (clear-stream _test-output-stream)
10496     (clear-stream $_test-output-buffered-file->buffer)
10497     #
10498     (write _test-input-stream "type t {\n")  # size = 12, which is not a power of 2
10499     (write _test-input-stream "  x: int\n")
10500     (write _test-input-stream "  y: int\n")
10501     (write _test-input-stream "  z: int\n")
10502     (write _test-input-stream "}\n")
10503     (write _test-input-stream "fn foo {\n")
10504     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
10505     (write _test-input-stream "  var x/eax: int <- length arr\n")
10506     (write _test-input-stream "}\n")
10507     # convert
10508     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
10509     (flush _test-output-buffered-file)
10510 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
10516     # check output
10517     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types-to-eax/0")
10518     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types-to-eax/1")
10519     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types-to-eax/2")
10520     (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")
10521     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types-to-eax/4")
10522     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types-to-eax/5")
10523     # var arr
10524     (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")
10525     (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")
10526     # length instruction
10527     (check-next-stream-line-equal _test-output-stream "    51/push-ecx"         "F - test-convert-length-of-array-of-user-defined-types-to-eax/8")
10528     (check-next-stream-line-equal _test-output-stream "    52/push-edx"         "F - test-convert-length-of-array-of-user-defined-types-to-eax/9")
10529     (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")
10530     (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")
10531     (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")
10532     (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")
10533     (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")
10534     (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")
10535     # reclaim arr
10536     (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")
10537     #
10538     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types-to-eax/17")
10539     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types-to-eax/18")
10540     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types-to-eax/19")
10541     (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")
10542     (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")
10543     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types-to-eax/22")
10544     # . epilogue
10545     89/<- %esp 5/r32/ebp
10546     5d/pop-to-ebp
10547     c3/return
10548 
10549 test-convert-length-of-array-of-user-defined-types-to-ecx:
10550     # . prologue
10551     55/push-ebp
10552     89/<- %ebp 4/r32/esp
10553     # setup
10554     (clear-stream _test-input-stream)
10555     (clear-stream $_test-input-buffered-file->buffer)
10556     (clear-stream _test-output-stream)
10557     (clear-stream $_test-output-buffered-file->buffer)
10558     #
10559     (write _test-input-stream "type t {\n")  # size = 12, which is not a power of 2
10560     (write _test-input-stream "  x: int\n")
10561     (write _test-input-stream "  y: int\n")
10562     (write _test-input-stream "  z: int\n")
10563     (write _test-input-stream "}\n")
10564     (write _test-input-stream "fn foo {\n")
10565     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
10566     (write _test-input-stream "  var x/ecx: int <- length arr\n")
10567     (write _test-input-stream "}\n")
10568     # convert
10569     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
10570     (flush _test-output-buffered-file)
10571 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
10577     # check output
10578     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types-to-ecx/0")
10579     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types-to-ecx/1")
10580     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types-to-ecx/2")
10581     (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")
10582     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types-to-ecx/4")
10583     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types-to-ecx/5")
10584     # var a
10585     (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")
10586     (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")
10587     # var x
10588     (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")
10589     # length instruction
10590     (check-next-stream-line-equal _test-output-stream "    50/push-eax"         "F - test-convert-length-of-array-of-user-defined-types-to-ecx/9")
10591     (check-next-stream-line-equal _test-output-stream "    52/push-edx"         "F - test-convert-length-of-array-of-user-defined-types-to-ecx/10")
10592     (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")
10593     (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")
10594     (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")
10595     (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")
10596     (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")
10597     (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")
10598     (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")
10599     # reclaim x
10600     (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")
10601     # reclaim a
10602     (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")
10603     #
10604     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types-to-ecx/20")
10605     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types-to-ecx/21")
10606     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types-to-ecx/22")
10607     (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")
10608     (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")
10609     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types-to-ecx/25")
10610     # . epilogue
10611     89/<- %esp 5/r32/ebp
10612     5d/pop-to-ebp
10613     c3/return
10614 
10615 test-convert-length-of-array-of-user-defined-types-to-edx:
10616     # . prologue
10617     55/push-ebp
10618     89/<- %ebp 4/r32/esp
10619     # setup
10620     (clear-stream _test-input-stream)
10621     (clear-stream $_test-input-buffered-file->buffer)
10622     (clear-stream _test-output-stream)
10623     (clear-stream $_test-output-buffered-file->buffer)
10624     #
10625     (write _test-input-stream "type t {\n")  # size = 12, which is not a power of 2
10626     (write _test-input-stream "  x: int\n")
10627     (write _test-input-stream "  y: int\n")
10628     (write _test-input-stream "  z: int\n")
10629     (write _test-input-stream "}\n")
10630     (write _test-input-stream "fn foo {\n")
10631     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
10632     (write _test-input-stream "  var x/edx: int <- length arr\n")
10633     (write _test-input-stream "}\n")
10634     # convert
10635     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
10636     (flush _test-output-buffered-file)
10637 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
10643     # check output
10644     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types-to-edx/0")
10645     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types-to-edx/1")
10646     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types-to-edx/2")
10647     (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")
10648     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types-to-edx/4")
10649     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types-to-edx/5")
10650     # var a
10651     (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")
10652     (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")
10653     # var x
10654     (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")
10655     # length instruction
10656     (check-next-stream-line-equal _test-output-stream "    50/push-eax"         "F - test-convert-length-of-array-of-user-defined-types-to-edx/9")
10657     (check-next-stream-line-equal _test-output-stream "    51/push-ecx"         "F - test-convert-length-of-array-of-user-defined-types-to-edx/10")
10658     (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")
10659     (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")
10660     (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")
10661     (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")
10662     (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")
10663     (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")
10664     (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")
10665     # reclaim x
10666     (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")
10667     # reclaim a
10668     (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")
10669     #
10670     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types-to-edx/20")
10671     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types-to-edx/21")
10672     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types-to-edx/22")
10673     (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")
10674     (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")
10675     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types-to-edx/25")
10676     # . epilogue
10677     89/<- %esp 5/r32/ebp
10678     5d/pop-to-ebp
10679     c3/return
10680 
10681 test-convert-length-of-array-of-user-defined-types:
10682     # . prologue
10683     55/push-ebp
10684     89/<- %ebp 4/r32/esp
10685     # setup
10686     (clear-stream _test-input-stream)
10687     (clear-stream $_test-input-buffered-file->buffer)
10688     (clear-stream _test-output-stream)
10689     (clear-stream $_test-output-buffered-file->buffer)
10690     #
10691     (write _test-input-stream "type t {\n")  # each t is 8 bytes, which is a power of 2
10692     (write _test-input-stream "  x: int\n")
10693     (write _test-input-stream "  y: int\n")
10694     (write _test-input-stream "  z: int\n")
10695     (write _test-input-stream "}\n")
10696     (write _test-input-stream "fn foo {\n")
10697     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
10698     (write _test-input-stream "  var x/ebx: int <- length arr\n")
10699     (write _test-input-stream "}\n")
10700     # convert
10701     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
10702     (flush _test-output-buffered-file)
10703 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
10709     # check output
10710     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types/0")
10711     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types/1")
10712     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types/2")
10713     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array-of-user-defined-types/3")
10714     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types/4")
10715     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types/5")
10716     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array-of-user-defined-types/6")
10717     (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")
10718     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ebx"  "F - test-convert-length-of-array-of-user-defined-types/8")
10719     (check-next-stream-line-equal _test-output-stream "    50/push-eax"         "F - test-convert-length-of-array-of-user-defined-types/9")
10720     (check-next-stream-line-equal _test-output-stream "    51/push-ecx"         "F - test-convert-length-of-array-of-user-defined-types/10")
10721     (check-next-stream-line-equal _test-output-stream "    52/push-edx"         "F - test-convert-length-of-array-of-user-defined-types/11")
10722     (check-next-stream-line-equal _test-output-stream "    8b/-> *eax 0x00000000/r32"  "F - test-convert-length-of-array-of-user-defined-types/12")
10723     (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")
10724     (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")
10725     (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")
10726     (check-next-stream-line-equal _test-output-stream "    89/<- %ebx 0/r32/eax"  "F - test-convert-length-of-array-of-user-defined-types/16")
10727     (check-next-stream-line-equal _test-output-stream "    5a/pop-to-edx"       "F - test-convert-length-of-array-of-user-defined-types/17")
10728     (check-next-stream-line-equal _test-output-stream "    59/pop-to-ecx"       "F - test-convert-length-of-array-of-user-defined-types/18")
10729     (check-next-stream-line-equal _test-output-stream "    58/pop-to-eax"       "F - test-convert-length-of-array-of-user-defined-types/19")
10730     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ebx"  "F - test-convert-length-of-array-of-user-defined-types/20")
10731     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array-of-user-defined-types/21")
10732     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types/22")
10733     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types/23")
10734     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types/24")
10735     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array-of-user-defined-types/25")
10736     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array-of-user-defined-types/26")
10737     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types/27")
10738     # . epilogue
10739     89/<- %esp 5/r32/ebp
10740     5d/pop-to-ebp
10741     c3/return
10742 
10743 test-index-with-non-array-atom-base-type:
10744     # . prologue
10745     55/push-ebp
10746     89/<- %ebp 4/r32/esp
10747     # setup
10748     (clear-stream _test-input-stream)
10749     (clear-stream $_test-input-buffered-file->buffer)
10750     (clear-stream _test-output-stream)
10751     (clear-stream $_test-output-buffered-file->buffer)
10752     (clear-stream _test-error-stream)
10753     (clear-stream $_test-error-buffered-file->buffer)
10754     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10755     68/push 0/imm32
10756     68/push 0/imm32
10757     89/<- %edx 4/r32/esp
10758     (tailor-exit-descriptor %edx 0x10)
10759     #
10760     (write _test-input-stream "fn foo {\n")
10761     (write _test-input-stream "  var a: int\n")
10762     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
10763     (write _test-input-stream "}\n")
10764     # convert
10765     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10766     # registers except esp clobbered at this point
10767     # restore ed
10768     89/<- %edx 4/r32/esp
10769     (flush _test-output-buffered-file)
10770     (flush _test-error-buffered-file)
10771 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10777     # check output
10778     (check-stream-equal _test-output-stream  ""  "F - test-index-with-non-array-atom-base-type: output should be empty")
10779     (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")
10780     # check that stop(1) was called
10781     (check-ints-equal *(edx+4) 2 "F - test-index-with-non-array-atom-base-type: exit status")
10782     # don't restore from ebp
10783     81 0/subop/add %esp 8/imm32
10784     # . epilogue
10785     5d/pop-to-ebp
10786     c3/return
10787 
10788 test-index-with-non-array-compound-base-type:
10789     # . prologue
10790     55/push-ebp
10791     89/<- %ebp 4/r32/esp
10792     # setup
10793     (clear-stream _test-input-stream)
10794     (clear-stream $_test-input-buffered-file->buffer)
10795     (clear-stream _test-output-stream)
10796     (clear-stream $_test-output-buffered-file->buffer)
10797     (clear-stream _test-error-stream)
10798     (clear-stream $_test-error-buffered-file->buffer)
10799     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10800     68/push 0/imm32
10801     68/push 0/imm32
10802     89/<- %edx 4/r32/esp
10803     (tailor-exit-descriptor %edx 0x10)
10804     #
10805     (write _test-input-stream "fn foo {\n")
10806     (write _test-input-stream "  var a: (handle int)\n")
10807     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
10808     (write _test-input-stream "}\n")
10809     # convert
10810     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10811     # registers except esp clobbered at this point
10812     # restore ed
10813     89/<- %edx 4/r32/esp
10814     (flush _test-output-buffered-file)
10815     (flush _test-error-buffered-file)
10816 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10822     # check output
10823     (check-stream-equal _test-output-stream  ""  "F - test-index-with-non-array-compound-base-type: output should be empty")
10824     (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")
10825     # check that stop(1) was called
10826     (check-ints-equal *(edx+4) 2 "F - test-index-with-non-array-compound-base-type: exit status")
10827     # don't restore from ebp
10828     81 0/subop/add %esp 8/imm32
10829     # . epilogue
10830     5d/pop-to-ebp
10831     c3/return
10832 
10833 test-index-with-non-array-compound-base-type-2:
10834     # . prologue
10835     55/push-ebp
10836     89/<- %ebp 4/r32/esp
10837     # setup
10838     (clear-stream _test-input-stream)
10839     (clear-stream $_test-input-buffered-file->buffer)
10840     (clear-stream _test-output-stream)
10841     (clear-stream $_test-output-buffered-file->buffer)
10842     (clear-stream _test-error-stream)
10843     (clear-stream $_test-error-buffered-file->buffer)
10844     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10845     68/push 0/imm32
10846     68/push 0/imm32
10847     89/<- %edx 4/r32/esp
10848     (tailor-exit-descriptor %edx 0x10)
10849     #
10850     (write _test-input-stream "fn foo {\n")
10851     (write _test-input-stream "  var a: (addr int)\n")
10852     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
10853     (write _test-input-stream "}\n")
10854     # convert
10855     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10856     # registers except esp clobbered at this point
10857     # restore ed
10858     89/<- %edx 4/r32/esp
10859     (flush _test-output-buffered-file)
10860     (flush _test-error-buffered-file)
10861 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10867     # check output
10868     (check-stream-equal _test-output-stream  ""  "F - test-index-with-non-array-compound-base-type-2: output should be empty")
10869     (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")
10870     # check that stop(1) was called
10871     (check-ints-equal *(edx+4) 2 "F - test-index-with-non-array-compound-base-type-2: exit status")
10872     # don't restore from ebp
10873     81 0/subop/add %esp 8/imm32
10874     # . epilogue
10875     5d/pop-to-ebp
10876     c3/return
10877 
10878 test-index-with-array-atom-base-type:
10879     # . prologue
10880     55/push-ebp
10881     89/<- %ebp 4/r32/esp
10882     # setup
10883     (clear-stream _test-input-stream)
10884     (clear-stream $_test-input-buffered-file->buffer)
10885     (clear-stream _test-output-stream)
10886     (clear-stream $_test-output-buffered-file->buffer)
10887     (clear-stream _test-error-stream)
10888     (clear-stream $_test-error-buffered-file->buffer)
10889     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10890     68/push 0/imm32
10891     68/push 0/imm32
10892     89/<- %edx 4/r32/esp
10893     (tailor-exit-descriptor %edx 0x10)
10894     #
10895     (write _test-input-stream "fn foo {\n")
10896     (write _test-input-stream "  var a: array\n")
10897     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
10898     (write _test-input-stream "}\n")
10899     # convert
10900     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10901     # registers except esp clobbered at this point
10902     # restore ed
10903     89/<- %edx 4/r32/esp
10904     (flush _test-output-buffered-file)
10905     (flush _test-error-buffered-file)
10906 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10912     # check output
10913     (check-stream-equal _test-output-stream  ""  "F - test-index-with-array-atom-base-type: output should be empty")
10914     (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")
10915     # check that stop(1) was called
10916     (check-ints-equal *(edx+4) 2 "F - test-index-with-array-atom-base-type: exit status")
10917     # don't restore from ebp
10918     81 0/subop/add %esp 8/imm32
10919     # . epilogue
10920     5d/pop-to-ebp
10921     c3/return
10922 
10923 test-index-with-addr-base-on-stack:
10924     # . prologue
10925     55/push-ebp
10926     89/<- %ebp 4/r32/esp
10927     # setup
10928     (clear-stream _test-input-stream)
10929     (clear-stream $_test-input-buffered-file->buffer)
10930     (clear-stream _test-output-stream)
10931     (clear-stream $_test-output-buffered-file->buffer)
10932     (clear-stream _test-error-stream)
10933     (clear-stream $_test-error-buffered-file->buffer)
10934     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10935     68/push 0/imm32
10936     68/push 0/imm32
10937     89/<- %edx 4/r32/esp
10938     (tailor-exit-descriptor %edx 0x10)
10939     #
10940     (write _test-input-stream "fn foo {\n")
10941     (write _test-input-stream "  var a: (addr array int)\n")
10942     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
10943     (write _test-input-stream "}\n")
10944     # convert
10945     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10946     # registers except esp clobbered at this point
10947     # restore ed
10948     89/<- %edx 4/r32/esp
10949     (flush _test-output-buffered-file)
10950     (flush _test-error-buffered-file)
10951 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10957     # check output
10958     (check-stream-equal _test-output-stream  ""  "F - test-index-with-addr-base-on-stack: output should be empty")
10959     (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")
10960     # check that stop(1) was called
10961     (check-ints-equal *(edx+4) 2 "F - test-index-with-addr-base-on-stack: exit status")
10962     # don't restore from ebp
10963     81 0/subop/add %esp 8/imm32
10964     # . epilogue
10965     5d/pop-to-ebp
10966     c3/return
10967 
10968 test-index-with-wrong-index-type:
10969     # . prologue
10970     55/push-ebp
10971     89/<- %ebp 4/r32/esp
10972     # setup
10973     (clear-stream _test-input-stream)
10974     (clear-stream $_test-input-buffered-file->buffer)
10975     (clear-stream _test-output-stream)
10976     (clear-stream $_test-output-buffered-file->buffer)
10977     (clear-stream _test-error-stream)
10978     (clear-stream $_test-error-buffered-file->buffer)
10979     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10980     68/push 0/imm32
10981     68/push 0/imm32
10982     89/<- %edx 4/r32/esp
10983     (tailor-exit-descriptor %edx 0x10)
10984     #
10985     (write _test-input-stream "fn foo {\n")
10986     (write _test-input-stream "  var a/eax: (addr array int) <- copy 0\n")
10987     (write _test-input-stream "  var b: boolean\n")
10988     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
10989     (write _test-input-stream "}\n")
10990     # convert
10991     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10992     # registers except esp clobbered at this point
10993     # restore ed
10994     89/<- %edx 4/r32/esp
10995     (flush _test-output-buffered-file)
10996     (flush _test-error-buffered-file)
10997 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11003     # check output
11004     (check-stream-equal _test-output-stream  ""  "F - test-index-with-wrong-index-type: output should be empty")
11005     (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")
11006     # check that stop(1) was called
11007     (check-ints-equal *(edx+4) 2 "F - test-index-with-wrong-index-type: exit status")
11008     # don't restore from ebp
11009     81 0/subop/add %esp 8/imm32
11010     # . epilogue
11011     5d/pop-to-ebp
11012     c3/return
11013 
11014 test-index-with-offset-atom-index-type:
11015     # . prologue
11016     55/push-ebp
11017     89/<- %ebp 4/r32/esp
11018     # setup
11019     (clear-stream _test-input-stream)
11020     (clear-stream $_test-input-buffered-file->buffer)
11021     (clear-stream _test-output-stream)
11022     (clear-stream $_test-output-buffered-file->buffer)
11023     (clear-stream _test-error-stream)
11024     (clear-stream $_test-error-buffered-file->buffer)
11025     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11026     68/push 0/imm32
11027     68/push 0/imm32
11028     89/<- %edx 4/r32/esp
11029     (tailor-exit-descriptor %edx 0x10)
11030     #
11031     (write _test-input-stream "fn foo {\n")
11032     (write _test-input-stream "  var a/eax: (addr array int) <- copy 0\n")
11033     (write _test-input-stream "  var b: offset\n")
11034     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
11035     (write _test-input-stream "}\n")
11036     # convert
11037     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11038     # registers except esp clobbered at this point
11039     # restore ed
11040     89/<- %edx 4/r32/esp
11041     (flush _test-output-buffered-file)
11042     (flush _test-error-buffered-file)
11043 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11049     # check output
11050     (check-stream-equal _test-output-stream  ""  "F - test-index-with-offset-atom-index-type: output should be empty")
11051     (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")
11052     # check that stop(1) was called
11053     (check-ints-equal *(edx+4) 2 "F - test-index-with-offset-atom-index-type: exit status")
11054     # don't restore from ebp
11055     81 0/subop/add %esp 8/imm32
11056     # . epilogue
11057     5d/pop-to-ebp
11058     c3/return
11059 
11060 test-index-with-offset-on-stack:
11061     # . prologue
11062     55/push-ebp
11063     89/<- %ebp 4/r32/esp
11064     # setup
11065     (clear-stream _test-input-stream)
11066     (clear-stream $_test-input-buffered-file->buffer)
11067     (clear-stream _test-output-stream)
11068     (clear-stream $_test-output-buffered-file->buffer)
11069     (clear-stream _test-error-stream)
11070     (clear-stream $_test-error-buffered-file->buffer)
11071     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11072     68/push 0/imm32
11073     68/push 0/imm32
11074     89/<- %edx 4/r32/esp
11075     (tailor-exit-descriptor %edx 0x10)
11076     #
11077     (write _test-input-stream "fn foo {\n")
11078     (write _test-input-stream "  var a/eax: (addr array int) <- copy 0\n")
11079     (write _test-input-stream "  var b: int\n")
11080     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
11081     (write _test-input-stream "}\n")
11082     # convert
11083     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11084     # registers except esp clobbered at this point
11085     # restore ed
11086     89/<- %edx 4/r32/esp
11087     (flush _test-output-buffered-file)
11088     (flush _test-error-buffered-file)
11089 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11095     # check output
11096     (check-stream-equal _test-output-stream  ""  "F - test-index-with-offset-on-stack: output should be empty")
11097     (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")
11098     # check that stop(1) was called
11099     (check-ints-equal *(edx+4) 2 "F - test-index-with-offset-on-stack: exit status")
11100     # don't restore from ebp
11101     81 0/subop/add %esp 8/imm32
11102     # . epilogue
11103     5d/pop-to-ebp
11104     c3/return
11105 
11106 test-index-needs-offset-type:
11107     # . prologue
11108     55/push-ebp
11109     89/<- %ebp 4/r32/esp
11110     # setup
11111     (clear-stream _test-input-stream)
11112     (clear-stream $_test-input-buffered-file->buffer)
11113     (clear-stream _test-output-stream)
11114     (clear-stream $_test-output-buffered-file->buffer)
11115     (clear-stream _test-error-stream)
11116     (clear-stream $_test-error-buffered-file->buffer)
11117     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11118     68/push 0/imm32
11119     68/push 0/imm32
11120     89/<- %edx 4/r32/esp
11121     (tailor-exit-descriptor %edx 0x10)
11122     #
11123     (write _test-input-stream "fn foo {\n")
11124     (write _test-input-stream "  var a/eax: (addr array t) <- copy 0\n")
11125     (write _test-input-stream "  var b/ebx: int <- copy 0\n")
11126     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
11127     (write _test-input-stream "}\n")
11128     (write _test-input-stream "type t {\n")  # size 12 is not a power of two
11129     (write _test-input-stream "  x: int\n")
11130     (write _test-input-stream "  y: int\n")
11131     (write _test-input-stream "  z: int\n")
11132     (write _test-input-stream "}\n")
11133     # convert
11134     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11135     # registers except esp clobbered at this point
11136     # restore ed
11137     89/<- %edx 4/r32/esp
11138     (flush _test-output-buffered-file)
11139     (flush _test-error-buffered-file)
11140 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11146     # check output
11147     (check-stream-equal _test-output-stream  ""  "F - test-index-needs-offset-type: output should be empty")
11148     (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")
11149     # check that stop(1) was called
11150     (check-ints-equal *(edx+4) 2 "F - test-index-needs-offset-type: exit status")
11151     # don't restore from ebp
11152     81 0/subop/add %esp 8/imm32
11153     # . epilogue
11154     5d/pop-to-ebp
11155     c3/return
11156 
11157 test-index-with-output-not-address:
11158     # . prologue
11159     55/push-ebp
11160     89/<- %ebp 4/r32/esp
11161     # setup
11162     (clear-stream _test-input-stream)
11163     (clear-stream $_test-input-buffered-file->buffer)
11164     (clear-stream _test-output-stream)
11165     (clear-stream $_test-output-buffered-file->buffer)
11166     (clear-stream _test-error-stream)
11167     (clear-stream $_test-error-buffered-file->buffer)
11168     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11169     68/push 0/imm32
11170     68/push 0/imm32
11171     89/<- %edx 4/r32/esp
11172     (tailor-exit-descriptor %edx 0x10)
11173     #
11174     (write _test-input-stream "fn foo {\n")
11175     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
11176     (write _test-input-stream "  var o/edi: int <- index a, 0\n")
11177     (write _test-input-stream "}\n")
11178     # convert
11179     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11180     # registers except esp clobbered at this point
11181     # restore ed
11182     89/<- %edx 4/r32/esp
11183     (flush _test-output-buffered-file)
11184     (flush _test-error-buffered-file)
11185 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11191     # check output
11192     (check-stream-equal _test-output-stream  ""  "F - test-index-with-output-not-address: output should be empty")
11193     (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")
11194     # check that stop(1) was called
11195     (check-ints-equal *(edx+4) 2 "F - test-index-with-output-not-address: exit status")
11196     # don't restore from ebp
11197     81 0/subop/add %esp 8/imm32
11198     # . epilogue
11199     5d/pop-to-ebp
11200     c3/return
11201 
11202 test-index-with-output-not-address-2:
11203     # . prologue
11204     55/push-ebp
11205     89/<- %ebp 4/r32/esp
11206     # setup
11207     (clear-stream _test-input-stream)
11208     (clear-stream $_test-input-buffered-file->buffer)
11209     (clear-stream _test-output-stream)
11210     (clear-stream $_test-output-buffered-file->buffer)
11211     (clear-stream _test-error-stream)
11212     (clear-stream $_test-error-buffered-file->buffer)
11213     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11214     68/push 0/imm32
11215     68/push 0/imm32
11216     89/<- %edx 4/r32/esp
11217     (tailor-exit-descriptor %edx 0x10)
11218     #
11219     (write _test-input-stream "fn foo {\n")
11220     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
11221     (write _test-input-stream "  var o/edi: (int) <- index a, 0\n")
11222     (write _test-input-stream "}\n")
11223     # convert
11224     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11225     # registers except esp clobbered at this point
11226     # restore ed
11227     89/<- %edx 4/r32/esp
11228     (flush _test-output-buffered-file)
11229     (flush _test-error-buffered-file)
11230 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11236     # check output
11237     (check-stream-equal _test-output-stream  ""  "F - test-index-with-output-not-address-2: output should be empty")
11238     (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")
11239     # check that stop(1) was called
11240     (check-ints-equal *(edx+4) 2 "F - test-index-with-output-not-address-2: exit status")
11241     # don't restore from ebp
11242     81 0/subop/add %esp 8/imm32
11243     # . epilogue
11244     5d/pop-to-ebp
11245     c3/return
11246 
11247 test-index-with-wrong-output-type:
11248     # . prologue
11249     55/push-ebp
11250     89/<- %ebp 4/r32/esp
11251     # setup
11252     (clear-stream _test-input-stream)
11253     (clear-stream $_test-input-buffered-file->buffer)
11254     (clear-stream _test-output-stream)
11255     (clear-stream $_test-output-buffered-file->buffer)
11256     (clear-stream _test-error-stream)
11257     (clear-stream $_test-error-buffered-file->buffer)
11258     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11259     68/push 0/imm32
11260     68/push 0/imm32
11261     89/<- %edx 4/r32/esp
11262     (tailor-exit-descriptor %edx 0x10)
11263     #
11264     (write _test-input-stream "fn foo {\n")
11265     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
11266     (write _test-input-stream "  var o/edi: (addr int) <- index a, 0\n")
11267     (write _test-input-stream "}\n")
11268     # convert
11269     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11270     # registers except esp clobbered at this point
11271     # restore ed
11272     89/<- %edx 4/r32/esp
11273     (flush _test-output-buffered-file)
11274     (flush _test-error-buffered-file)
11275 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11281     # check output
11282     (check-stream-equal _test-output-stream  ""  "F - test-index-with-wrong-output-type: output should be empty")
11283     (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")
11284     # check that stop(1) was called
11285     (check-ints-equal *(edx+4) 2 "F - test-index-with-wrong-output-type: exit status")
11286     # don't restore from ebp
11287     81 0/subop/add %esp 8/imm32
11288     # . epilogue
11289     5d/pop-to-ebp
11290     c3/return
11291 
11292 test-index-with-wrong-output-compound-type:
11293     # . prologue
11294     55/push-ebp
11295     89/<- %ebp 4/r32/esp
11296     # setup
11297     (clear-stream _test-input-stream)
11298     (clear-stream $_test-input-buffered-file->buffer)
11299     (clear-stream _test-output-stream)
11300     (clear-stream $_test-output-buffered-file->buffer)
11301     (clear-stream _test-error-stream)
11302     (clear-stream $_test-error-buffered-file->buffer)
11303     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11304     68/push 0/imm32
11305     68/push 0/imm32
11306     89/<- %edx 4/r32/esp
11307     (tailor-exit-descriptor %edx 0x10)
11308     #
11309     (write _test-input-stream "fn foo {\n")
11310     (write _test-input-stream "  var a/ebx: (addr array handle boolean) <- copy 0\n")
11311     (write _test-input-stream "  var o/edi: (addr handle int) <- index a, 0\n")
11312     (write _test-input-stream "}\n")
11313     # convert
11314     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11315     # registers except esp clobbered at this point
11316     # restore ed
11317     89/<- %edx 4/r32/esp
11318     (flush _test-output-buffered-file)
11319     (flush _test-error-buffered-file)
11320 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11326     # check output
11327     (check-stream-equal _test-output-stream  ""  "F - test-index-with-wrong-output-compound-type: output should be empty")
11328     (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")
11329     # check that stop(1) was called
11330     (check-ints-equal *(edx+4) 2 "F - test-index-with-wrong-output-compound-type: exit status")
11331     # don't restore from ebp
11332     81 0/subop/add %esp 8/imm32
11333     # . epilogue
11334     5d/pop-to-ebp
11335     c3/return
11336 
11337 test-index-with-no-inouts:
11338     # . prologue
11339     55/push-ebp
11340     89/<- %ebp 4/r32/esp
11341     # setup
11342     (clear-stream _test-input-stream)
11343     (clear-stream $_test-input-buffered-file->buffer)
11344     (clear-stream _test-output-stream)
11345     (clear-stream $_test-output-buffered-file->buffer)
11346     (clear-stream _test-error-stream)
11347     (clear-stream $_test-error-buffered-file->buffer)
11348     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11349     68/push 0/imm32
11350     68/push 0/imm32
11351     89/<- %edx 4/r32/esp
11352     (tailor-exit-descriptor %edx 0x10)
11353     #
11354     (write _test-input-stream "fn foo {\n")
11355     (write _test-input-stream "  var c/ecx: (addr int) <- index\n")
11356     (write _test-input-stream "}\n")
11357     # convert
11358     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11359     # registers except esp clobbered at this point
11360     # restore ed
11361     89/<- %edx 4/r32/esp
11362     (flush _test-output-buffered-file)
11363     (flush _test-error-buffered-file)
11364 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11370     # check output
11371     (check-stream-equal _test-output-stream  ""  "F - test-index-with-no-inouts: output should be empty")
11372     (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")
11373     # check that stop(1) was called
11374     (check-ints-equal *(edx+4) 2 "F - test-index-with-no-inouts: exit status")
11375     # don't restore from ebp
11376     81 0/subop/add %esp 8/imm32
11377     # . epilogue
11378     5d/pop-to-ebp
11379     c3/return
11380 
11381 test-index-with-too-few-inouts:
11382     # . prologue
11383     55/push-ebp
11384     89/<- %ebp 4/r32/esp
11385     # setup
11386     (clear-stream _test-input-stream)
11387     (clear-stream $_test-input-buffered-file->buffer)
11388     (clear-stream _test-output-stream)
11389     (clear-stream $_test-output-buffered-file->buffer)
11390     (clear-stream _test-error-stream)
11391     (clear-stream $_test-error-buffered-file->buffer)
11392     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11393     68/push 0/imm32
11394     68/push 0/imm32
11395     89/<- %edx 4/r32/esp
11396     (tailor-exit-descriptor %edx 0x10)
11397     #
11398     (write _test-input-stream "fn foo {\n")
11399     (write _test-input-stream "  var a: (array int 3)\n")
11400     (write _test-input-stream "  var c/ecx: (addr int) <- index a\n")
11401     (write _test-input-stream "}\n")
11402     # convert
11403     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11404     # registers except esp clobbered at this point
11405     # restore ed
11406     89/<- %edx 4/r32/esp
11407     (flush _test-output-buffered-file)
11408     (flush _test-error-buffered-file)
11409 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11415     # check output
11416     (check-stream-equal _test-output-stream  ""  "F - test-index-with-too-few-inouts: output should be empty")
11417     (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")
11418     # check that stop(1) was called
11419     (check-ints-equal *(edx+4) 2 "F - test-index-with-too-few-inouts: exit status")
11420     # don't restore from ebp
11421     81 0/subop/add %esp 8/imm32
11422     # . epilogue
11423     5d/pop-to-ebp
11424     c3/return
11425 
11426 test-index-with-too-many-inouts:
11427     # . prologue
11428     55/push-ebp
11429     89/<- %ebp 4/r32/esp
11430     # setup
11431     (clear-stream _test-input-stream)
11432     (clear-stream $_test-input-buffered-file->buffer)
11433     (clear-stream _test-output-stream)
11434     (clear-stream $_test-output-buffered-file->buffer)
11435     (clear-stream _test-error-stream)
11436     (clear-stream $_test-error-buffered-file->buffer)
11437     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11438     68/push 0/imm32
11439     68/push 0/imm32
11440     89/<- %edx 4/r32/esp
11441     (tailor-exit-descriptor %edx 0x10)
11442     #
11443     (write _test-input-stream "fn foo {\n")
11444     (write _test-input-stream "  var a: (array int 3)\n")
11445     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0, 0\n")
11446     (write _test-input-stream "}\n")
11447     # convert
11448     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11449     # registers except esp clobbered at this point
11450     # restore ed
11451     89/<- %edx 4/r32/esp
11452     (flush _test-output-buffered-file)
11453     (flush _test-error-buffered-file)
11454 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11460     # check output
11461     (check-stream-equal _test-output-stream  ""  "F - test-index-with-too-many-inouts: output should be empty")
11462     (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")
11463     # check that stop(1) was called
11464     (check-ints-equal *(edx+4) 2 "F - test-index-with-too-many-inouts: exit status")
11465     # don't restore from ebp
11466     81 0/subop/add %esp 8/imm32
11467     # . epilogue
11468     5d/pop-to-ebp
11469     c3/return
11470 
11471 test-index-with-no-output:
11472     # . prologue
11473     55/push-ebp
11474     89/<- %ebp 4/r32/esp
11475     # setup
11476     (clear-stream _test-input-stream)
11477     (clear-stream $_test-input-buffered-file->buffer)
11478     (clear-stream _test-output-stream)
11479     (clear-stream $_test-output-buffered-file->buffer)
11480     (clear-stream _test-error-stream)
11481     (clear-stream $_test-error-buffered-file->buffer)
11482     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11483     68/push 0/imm32
11484     68/push 0/imm32
11485     89/<- %edx 4/r32/esp
11486     (tailor-exit-descriptor %edx 0x10)
11487     #
11488     (write _test-input-stream "fn foo {\n")
11489     (write _test-input-stream "  var a: (array int 3)\n")
11490     (write _test-input-stream "  index a, 0\n")
11491     (write _test-input-stream "}\n")
11492     # convert
11493     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11494     # registers except esp clobbered at this point
11495     # restore ed
11496     89/<- %edx 4/r32/esp
11497     (flush _test-output-buffered-file)
11498     (flush _test-error-buffered-file)
11499 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11505     # check output
11506     (check-stream-equal _test-output-stream  ""  "F - test-index-with-no-output: output should be empty")
11507     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: must have an output"  "F - test-index-with-no-output: error message")
11508     # check that stop(1) was called
11509     (check-ints-equal *(edx+4) 2 "F - test-index-with-no-output: exit status")
11510     # don't restore from ebp
11511     81 0/subop/add %esp 8/imm32
11512     # . epilogue
11513     5d/pop-to-ebp
11514     c3/return
11515 
11516 test-index-with-too-many-outputs:
11517     # . prologue
11518     55/push-ebp
11519     89/<- %ebp 4/r32/esp
11520     # setup
11521     (clear-stream _test-input-stream)
11522     (clear-stream $_test-input-buffered-file->buffer)
11523     (clear-stream _test-output-stream)
11524     (clear-stream $_test-output-buffered-file->buffer)
11525     (clear-stream _test-error-stream)
11526     (clear-stream $_test-error-buffered-file->buffer)
11527     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11528     68/push 0/imm32
11529     68/push 0/imm32
11530     89/<- %edx 4/r32/esp
11531     (tailor-exit-descriptor %edx 0x10)
11532     #
11533     (write _test-input-stream "fn foo {\n")
11534     (write _test-input-stream "  var a: (array int 3)\n")
11535     (write _test-input-stream "  var b/eax: (addr int) <- copy 0\n")
11536     (write _test-input-stream "  var c/ecx: (addr int) <- copy 0\n")
11537     (write _test-input-stream "  b, c <- index a, 0\n")
11538     (write _test-input-stream "}\n")
11539     # convert
11540     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11541     # registers except esp clobbered at this point
11542     # restore ed
11543     89/<- %edx 4/r32/esp
11544     (flush _test-output-buffered-file)
11545     (flush _test-error-buffered-file)
11546 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11552     # check output
11553     (check-stream-equal _test-output-stream  ""  "F - test-index-with-too-many-outputs: output should be empty")
11554     (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")
11555     # check that stop(1) was called
11556     (check-ints-equal *(edx+4) 2 "F - test-index-with-too-many-outputs: exit status")
11557     # don't restore from ebp
11558     81 0/subop/add %esp 8/imm32
11559     # . epilogue
11560     5d/pop-to-ebp
11561     c3/return
11562 
11563 test-compute-offset-with-non-array-atom-base-type:
11564     # . prologue
11565     55/push-ebp
11566     89/<- %ebp 4/r32/esp
11567     # setup
11568     (clear-stream _test-input-stream)
11569     (clear-stream $_test-input-buffered-file->buffer)
11570     (clear-stream _test-output-stream)
11571     (clear-stream $_test-output-buffered-file->buffer)
11572     (clear-stream _test-error-stream)
11573     (clear-stream $_test-error-buffered-file->buffer)
11574     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11575     68/push 0/imm32
11576     68/push 0/imm32
11577     89/<- %edx 4/r32/esp
11578     (tailor-exit-descriptor %edx 0x10)
11579     #
11580     (write _test-input-stream "fn foo {\n")
11581     (write _test-input-stream "  var a: int\n")
11582     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0\n")
11583     (write _test-input-stream "}\n")
11584     # convert
11585     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11586     # registers except esp clobbered at this point
11587     # restore ed
11588     89/<- %edx 4/r32/esp
11589     (flush _test-output-buffered-file)
11590     (flush _test-error-buffered-file)
11591 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11597     # check output
11598     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-non-array-atom-base-type: output should be empty")
11599     (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")
11600     # check that stop(1) was called
11601     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-non-array-atom-base-type: exit status")
11602     # don't restore from ebp
11603     81 0/subop/add %esp 8/imm32
11604     # . epilogue
11605     5d/pop-to-ebp
11606     c3/return
11607 
11608 test-compute-offset-with-non-array-compound-base-type:
11609     # . prologue
11610     55/push-ebp
11611     89/<- %ebp 4/r32/esp
11612     # setup
11613     (clear-stream _test-input-stream)
11614     (clear-stream $_test-input-buffered-file->buffer)
11615     (clear-stream _test-output-stream)
11616     (clear-stream $_test-output-buffered-file->buffer)
11617     (clear-stream _test-error-stream)
11618     (clear-stream $_test-error-buffered-file->buffer)
11619     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11620     68/push 0/imm32
11621     68/push 0/imm32
11622     89/<- %edx 4/r32/esp
11623     (tailor-exit-descriptor %edx 0x10)
11624     #
11625     (write _test-input-stream "fn foo {\n")
11626     (write _test-input-stream "  var a: (handle int)\n")
11627     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0\n")
11628     (write _test-input-stream "}\n")
11629     # convert
11630     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11631     # registers except esp clobbered at this point
11632     # restore ed
11633     89/<- %edx 4/r32/esp
11634     (flush _test-output-buffered-file)
11635     (flush _test-error-buffered-file)
11636 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11642     # check output
11643     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-non-array-compound-base-type: output should be empty")
11644     (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")
11645     # check that stop(1) was called
11646     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-non-array-compound-base-type: exit status")
11647     # don't restore from ebp
11648     81 0/subop/add %esp 8/imm32
11649     # . epilogue
11650     5d/pop-to-ebp
11651     c3/return
11652 
11653 test-compute-offset-with-non-array-compound-base-type-2:
11654     # . prologue
11655     55/push-ebp
11656     89/<- %ebp 4/r32/esp
11657     # setup
11658     (clear-stream _test-input-stream)
11659     (clear-stream $_test-input-buffered-file->buffer)
11660     (clear-stream _test-output-stream)
11661     (clear-stream $_test-output-buffered-file->buffer)
11662     (clear-stream _test-error-stream)
11663     (clear-stream $_test-error-buffered-file->buffer)
11664     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11665     68/push 0/imm32
11666     68/push 0/imm32
11667     89/<- %edx 4/r32/esp
11668     (tailor-exit-descriptor %edx 0x10)
11669     #
11670     (write _test-input-stream "fn foo {\n")
11671     (write _test-input-stream "  var a: (addr int)\n")
11672     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0\n")
11673     (write _test-input-stream "}\n")
11674     # convert
11675     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11676     # registers except esp clobbered at this point
11677     # restore ed
11678     89/<- %edx 4/r32/esp
11679     (flush _test-output-buffered-file)
11680     (flush _test-error-buffered-file)
11681 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11687     # check output
11688     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-non-array-compound-base-type-2: output should be empty")
11689     (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")
11690     # check that stop(1) was called
11691     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-non-array-compound-base-type-2: exit status")
11692     # don't restore from ebp
11693     81 0/subop/add %esp 8/imm32
11694     # . epilogue
11695     5d/pop-to-ebp
11696     c3/return
11697 
11698 test-compute-offset-with-array-atom-base-type:
11699     # . prologue
11700     55/push-ebp
11701     89/<- %ebp 4/r32/esp
11702     # setup
11703     (clear-stream _test-input-stream)
11704     (clear-stream $_test-input-buffered-file->buffer)
11705     (clear-stream _test-output-stream)
11706     (clear-stream $_test-output-buffered-file->buffer)
11707     (clear-stream _test-error-stream)
11708     (clear-stream $_test-error-buffered-file->buffer)
11709     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11710     68/push 0/imm32
11711     68/push 0/imm32
11712     89/<- %edx 4/r32/esp
11713     (tailor-exit-descriptor %edx 0x10)
11714     #
11715     (write _test-input-stream "fn foo {\n")
11716     (write _test-input-stream "  var a: array\n")
11717     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0\n")
11718     (write _test-input-stream "}\n")
11719     # convert
11720     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11721     # registers except esp clobbered at this point
11722     # restore ed
11723     89/<- %edx 4/r32/esp
11724     (flush _test-output-buffered-file)
11725     (flush _test-error-buffered-file)
11726 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11732     # check output
11733     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-array-atom-base-type: output should be empty")
11734     (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")
11735     # check that stop(1) was called
11736     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-array-atom-base-type: exit status")
11737     # don't restore from ebp
11738     81 0/subop/add %esp 8/imm32
11739     # . epilogue
11740     5d/pop-to-ebp
11741     c3/return
11742 
11743 test-compute-offset-with-wrong-index-type:
11744     # . prologue
11745     55/push-ebp
11746     89/<- %ebp 4/r32/esp
11747     # setup
11748     (clear-stream _test-input-stream)
11749     (clear-stream $_test-input-buffered-file->buffer)
11750     (clear-stream _test-output-stream)
11751     (clear-stream $_test-output-buffered-file->buffer)
11752     (clear-stream _test-error-stream)
11753     (clear-stream $_test-error-buffered-file->buffer)
11754     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11755     68/push 0/imm32
11756     68/push 0/imm32
11757     89/<- %edx 4/r32/esp
11758     (tailor-exit-descriptor %edx 0x10)
11759     #
11760     (write _test-input-stream "fn foo {\n")
11761     (write _test-input-stream "  var a/eax: (addr array int) <- copy 0\n")
11762     (write _test-input-stream "  var b: boolean\n")
11763     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, b\n")
11764     (write _test-input-stream "}\n")
11765     # convert
11766     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11767     # registers except esp clobbered at this point
11768     # restore ed
11769     89/<- %edx 4/r32/esp
11770     (flush _test-output-buffered-file)
11771     (flush _test-error-buffered-file)
11772 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11778     # check output
11779     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-wrong-index-type: output should be empty")
11780     (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")
11781     # check that stop(1) was called
11782     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-wrong-index-type: exit status")
11783     # don't restore from ebp
11784     81 0/subop/add %esp 8/imm32
11785     # . epilogue
11786     5d/pop-to-ebp
11787     c3/return
11788 
11789 test-compute-offset-with-output-not-offset:
11790     # . prologue
11791     55/push-ebp
11792     89/<- %ebp 4/r32/esp
11793     # setup
11794     (clear-stream _test-input-stream)
11795     (clear-stream $_test-input-buffered-file->buffer)
11796     (clear-stream _test-output-stream)
11797     (clear-stream $_test-output-buffered-file->buffer)
11798     (clear-stream _test-error-stream)
11799     (clear-stream $_test-error-buffered-file->buffer)
11800     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11801     68/push 0/imm32
11802     68/push 0/imm32
11803     89/<- %edx 4/r32/esp
11804     (tailor-exit-descriptor %edx 0x10)
11805     #
11806     (write _test-input-stream "fn foo {\n")
11807     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
11808     (write _test-input-stream "  var o/edi: int <- compute-offset a, 0\n")
11809     (write _test-input-stream "}\n")
11810     # convert
11811     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11812     # registers except esp clobbered at this point
11813     # restore ed
11814     89/<- %edx 4/r32/esp
11815     (flush _test-output-buffered-file)
11816     (flush _test-error-buffered-file)
11817 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11823     # check output
11824     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-output-not-offset: output should be empty")
11825     (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")
11826     # check that stop(1) was called
11827     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-output-not-offset: exit status")
11828     # don't restore from ebp
11829     81 0/subop/add %esp 8/imm32
11830     # . epilogue
11831     5d/pop-to-ebp
11832     c3/return
11833 
11834 test-compute-offset-with-output-not-address-2:
11835     # . prologue
11836     55/push-ebp
11837     89/<- %ebp 4/r32/esp
11838     # setup
11839     (clear-stream _test-input-stream)
11840     (clear-stream $_test-input-buffered-file->buffer)
11841     (clear-stream _test-output-stream)
11842     (clear-stream $_test-output-buffered-file->buffer)
11843     (clear-stream _test-error-stream)
11844     (clear-stream $_test-error-buffered-file->buffer)
11845     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11846     68/push 0/imm32
11847     68/push 0/imm32
11848     89/<- %edx 4/r32/esp
11849     (tailor-exit-descriptor %edx 0x10)
11850     #
11851     (write _test-input-stream "fn foo {\n")
11852     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
11853     (write _test-input-stream "  var o/edi: (int) <- compute-offset a, 0\n")
11854     (write _test-input-stream "}\n")
11855     # convert
11856     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11857     # registers except esp clobbered at this point
11858     # restore ed
11859     89/<- %edx 4/r32/esp
11860     (flush _test-output-buffered-file)
11861     (flush _test-error-buffered-file)
11862 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11868     # check output
11869     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-output-not-address-2: output should be empty")
11870     (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")
11871     # check that stop(1) was called
11872     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-output-not-address-2: exit status")
11873     # don't restore from ebp
11874     81 0/subop/add %esp 8/imm32
11875     # . epilogue
11876     5d/pop-to-ebp
11877     c3/return
11878 
11879 test-compute-offset-with-wrong-output-type:
11880     # . prologue
11881     55/push-ebp
11882     89/<- %ebp 4/r32/esp
11883     # setup
11884     (clear-stream _test-input-stream)
11885     (clear-stream $_test-input-buffered-file->buffer)
11886     (clear-stream _test-output-stream)
11887     (clear-stream $_test-output-buffered-file->buffer)
11888     (clear-stream _test-error-stream)
11889     (clear-stream $_test-error-buffered-file->buffer)
11890     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11891     68/push 0/imm32
11892     68/push 0/imm32
11893     89/<- %edx 4/r32/esp
11894     (tailor-exit-descriptor %edx 0x10)
11895     #
11896     (write _test-input-stream "fn foo {\n")
11897     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
11898     (write _test-input-stream "  var o/edi: (offset int) <- compute-offset a, 0\n")
11899     (write _test-input-stream "}\n")
11900     # convert
11901     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11902     # registers except esp clobbered at this point
11903     # restore ed
11904     89/<- %edx 4/r32/esp
11905     (flush _test-output-buffered-file)
11906     (flush _test-error-buffered-file)
11907 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11913     # check output
11914     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-wrong-output-type: output should be empty")
11915     (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")
11916     # check that stop(1) was called
11917     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-wrong-output-type: exit status")
11918     # don't restore from ebp
11919     81 0/subop/add %esp 8/imm32
11920     # . epilogue
11921     5d/pop-to-ebp
11922     c3/return
11923 
11924 test-compute-offset-with-wrong-output-compound-type:
11925     # . prologue
11926     55/push-ebp
11927     89/<- %ebp 4/r32/esp
11928     # setup
11929     (clear-stream _test-input-stream)
11930     (clear-stream $_test-input-buffered-file->buffer)
11931     (clear-stream _test-output-stream)
11932     (clear-stream $_test-output-buffered-file->buffer)
11933     (clear-stream _test-error-stream)
11934     (clear-stream $_test-error-buffered-file->buffer)
11935     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11936     68/push 0/imm32
11937     68/push 0/imm32
11938     89/<- %edx 4/r32/esp
11939     (tailor-exit-descriptor %edx 0x10)
11940     #
11941     (write _test-input-stream "fn foo {\n")
11942     (write _test-input-stream "  var a/ebx: (addr array handle boolean) <- copy 0\n")
11943     (write _test-input-stream "  var o/edi: (offset handle int) <- compute-offset a, 0\n")
11944     (write _test-input-stream "}\n")
11945     # convert
11946     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11947     # registers except esp clobbered at this point
11948     # restore ed
11949     89/<- %edx 4/r32/esp
11950     (flush _test-output-buffered-file)
11951     (flush _test-error-buffered-file)
11952 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11958     # check output
11959     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-wrong-output-compound-type: output should be empty")
11960     (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")
11961     # check that stop(1) was called
11962     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-wrong-output-compound-type: exit status")
11963     # don't restore from ebp
11964     81 0/subop/add %esp 8/imm32
11965     # . epilogue
11966     5d/pop-to-ebp
11967     c3/return
11968 
11969 test-compute-offset-with-no-inouts:
11970     # . prologue
11971     55/push-ebp
11972     89/<- %ebp 4/r32/esp
11973     # setup
11974     (clear-stream _test-input-stream)
11975     (clear-stream $_test-input-buffered-file->buffer)
11976     (clear-stream _test-output-stream)
11977     (clear-stream $_test-output-buffered-file->buffer)
11978     (clear-stream _test-error-stream)
11979     (clear-stream $_test-error-buffered-file->buffer)
11980     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11981     68/push 0/imm32
11982     68/push 0/imm32
11983     89/<- %edx 4/r32/esp
11984     (tailor-exit-descriptor %edx 0x10)
11985     #
11986     (write _test-input-stream "fn foo {\n")
11987     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset\n")
11988     (write _test-input-stream "}\n")
11989     # convert
11990     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11991     # registers except esp clobbered at this point
11992     # restore ed
11993     89/<- %edx 4/r32/esp
11994     (flush _test-output-buffered-file)
11995     (flush _test-error-buffered-file)
11996 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12002     # check output
12003     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-no-inouts: output should be empty")
12004     (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")
12005     # check that stop(1) was called
12006     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-no-inouts: exit status")
12007     # don't restore from ebp
12008     81 0/subop/add %esp 8/imm32
12009     # . epilogue
12010     5d/pop-to-ebp
12011     c3/return
12012 
12013 test-compute-offset-with-too-few-inouts:
12014     # . prologue
12015     55/push-ebp
12016     89/<- %ebp 4/r32/esp
12017     # setup
12018     (clear-stream _test-input-stream)
12019     (clear-stream $_test-input-buffered-file->buffer)
12020     (clear-stream _test-output-stream)
12021     (clear-stream $_test-output-buffered-file->buffer)
12022     (clear-stream _test-error-stream)
12023     (clear-stream $_test-error-buffered-file->buffer)
12024     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12025     68/push 0/imm32
12026     68/push 0/imm32
12027     89/<- %edx 4/r32/esp
12028     (tailor-exit-descriptor %edx 0x10)
12029     #
12030     (write _test-input-stream "fn foo {\n")
12031     (write _test-input-stream "  var a: (array int 3)\n")
12032     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a\n")
12033     (write _test-input-stream "}\n")
12034     # convert
12035     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12036     # registers except esp clobbered at this point
12037     # restore ed
12038     89/<- %edx 4/r32/esp
12039     (flush _test-output-buffered-file)
12040     (flush _test-error-buffered-file)
12041 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12047     # check output
12048     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-too-few-inouts: output should be empty")
12049     (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")
12050     # check that stop(1) was called
12051     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-too-few-inouts: exit status")
12052     # don't restore from ebp
12053     81 0/subop/add %esp 8/imm32
12054     # . epilogue
12055     5d/pop-to-ebp
12056     c3/return
12057 
12058 test-compute-offset-with-too-many-inouts:
12059     # . prologue
12060     55/push-ebp
12061     89/<- %ebp 4/r32/esp
12062     # setup
12063     (clear-stream _test-input-stream)
12064     (clear-stream $_test-input-buffered-file->buffer)
12065     (clear-stream _test-output-stream)
12066     (clear-stream $_test-output-buffered-file->buffer)
12067     (clear-stream _test-error-stream)
12068     (clear-stream $_test-error-buffered-file->buffer)
12069     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12070     68/push 0/imm32
12071     68/push 0/imm32
12072     89/<- %edx 4/r32/esp
12073     (tailor-exit-descriptor %edx 0x10)
12074     #
12075     (write _test-input-stream "fn foo {\n")
12076     (write _test-input-stream "  var a: (array int 3)\n")
12077     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0, 0\n")
12078     (write _test-input-stream "}\n")
12079     # convert
12080     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12081     # registers except esp clobbered at this point
12082     # restore ed
12083     89/<- %edx 4/r32/esp
12084     (flush _test-output-buffered-file)
12085     (flush _test-error-buffered-file)
12086 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12092     # check output
12093     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-too-many-inouts: output should be empty")
12094     (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")
12095     # check that stop(1) was called
12096     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-too-many-inouts: exit status")
12097     # don't restore from ebp
12098     81 0/subop/add %esp 8/imm32
12099     # . epilogue
12100     5d/pop-to-ebp
12101     c3/return
12102 
12103 test-compute-offset-with-no-output:
12104     # . prologue
12105     55/push-ebp
12106     89/<- %ebp 4/r32/esp
12107     # setup
12108     (clear-stream _test-input-stream)
12109     (clear-stream $_test-input-buffered-file->buffer)
12110     (clear-stream _test-output-stream)
12111     (clear-stream $_test-output-buffered-file->buffer)
12112     (clear-stream _test-error-stream)
12113     (clear-stream $_test-error-buffered-file->buffer)
12114     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12115     68/push 0/imm32
12116     68/push 0/imm32
12117     89/<- %edx 4/r32/esp
12118     (tailor-exit-descriptor %edx 0x10)
12119     #
12120     (write _test-input-stream "fn foo {\n")
12121     (write _test-input-stream "  var a: (array int 3)\n")
12122     (write _test-input-stream "  compute-offset a, 0\n")
12123     (write _test-input-stream "}\n")
12124     # convert
12125     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12126     # registers except esp clobbered at this point
12127     # restore ed
12128     89/<- %edx 4/r32/esp
12129     (flush _test-output-buffered-file)
12130     (flush _test-error-buffered-file)
12131 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12137     # check output
12138     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-no-output: output should be empty")
12139     (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")
12140     # check that stop(1) was called
12141     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-no-output: exit status")
12142     # don't restore from ebp
12143     81 0/subop/add %esp 8/imm32
12144     # . epilogue
12145     5d/pop-to-ebp
12146     c3/return
12147 
12148 test-compute-offset-with-too-many-outputs:
12149     # . prologue
12150     55/push-ebp
12151     89/<- %ebp 4/r32/esp
12152     # setup
12153     (clear-stream _test-input-stream)
12154     (clear-stream $_test-input-buffered-file->buffer)
12155     (clear-stream _test-output-stream)
12156     (clear-stream $_test-output-buffered-file->buffer)
12157     (clear-stream _test-error-stream)
12158     (clear-stream $_test-error-buffered-file->buffer)
12159     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12160     68/push 0/imm32
12161     68/push 0/imm32
12162     89/<- %edx 4/r32/esp
12163     (tailor-exit-descriptor %edx 0x10)
12164     #
12165     (write _test-input-stream "fn foo {\n")
12166     (write _test-input-stream "  var a: (array int 3)\n")
12167     (write _test-input-stream "  var b/eax: (offset int) <- compute-offset a, 0\n")
12168     (write _test-input-stream "  var c/ecx: (addr int) <- copy 0\n")
12169     (write _test-input-stream "  b, c <- compute-offset a, 0\n")
12170     (write _test-input-stream "}\n")
12171     # convert
12172     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12173     # registers except esp clobbered at this point
12174     # restore ed
12175     89/<- %edx 4/r32/esp
12176     (flush _test-output-buffered-file)
12177     (flush _test-error-buffered-file)
12178 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12184     # check output
12185     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-too-many-outputs: output should be empty")
12186     (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")
12187     # check that stop(1) was called
12188     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-too-many-outputs: exit status")
12189     # don't restore from ebp
12190     81 0/subop/add %esp 8/imm32
12191     # . epilogue
12192     5d/pop-to-ebp
12193     c3/return
12194 
12195 test-convert-read-from-stream:
12196     # . prologue
12197     55/push-ebp
12198     89/<- %ebp 4/r32/esp
12199     # setup
12200     (clear-stream _test-input-stream)
12201     (clear-stream $_test-input-buffered-file->buffer)
12202     (clear-stream _test-output-stream)
12203     (clear-stream $_test-output-buffered-file->buffer)
12204     #
12205     (write _test-input-stream "fn foo {\n")
12206     (write _test-input-stream "  var s/esi: (addr stream int) <- copy 0\n")
12207     (write _test-input-stream "  var o/ecx: (addr int) <- copy 0\n")
12208     (write _test-input-stream "  read-from-stream s, o\n")
12209     (write _test-input-stream "}\n")
12210     # convert
12211     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
12212     # registers except esp clobbered at this point
12213     # restore ed
12214     89/<- %edx 4/r32/esp
12215     (flush _test-output-buffered-file)
12216     (flush _test-error-buffered-file)
12217 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
12223     # check output
12224     (check-next-stream-line-equal _test-output-stream "foo:"                            "F - test-convert-read-from-stream/0")
12225     (check-next-stream-line-equal _test-output-stream "  # . prologue"                  "F - test-convert-read-from-stream/1")
12226     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                   "F - test-convert-read-from-stream/2")
12227     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"          "F - test-convert-read-from-stream/3")
12228     (check-next-stream-line-equal _test-output-stream "  {"                             "F - test-convert-read-from-stream/4")
12229     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"           "F - test-convert-read-from-stream/5")
12230     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %esi"        "F - test-convert-read-from-stream/6")
12231     (check-next-stream-line-equal _test-output-stream "    be/copy-to-esi 0/imm32"      "F - test-convert-read-from-stream/7")
12232     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"        "F - test-convert-read-from-stream/8")
12233     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"      "F - test-convert-read-from-stream/9")
12234     (check-next-stream-line-equal _test-output-stream "    (read-from-stream %esi %ecx 0x00000004)"  "F - test-convert-read-from-stream/10")
12235     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-read-from-stream/11")
12236     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %esi"         "F - test-convert-read-from-stream/12")
12237     (check-next-stream-line-equal _test-output-stream "  }"                             "F - test-convert-read-from-stream/13")
12238     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"          "F - test-convert-read-from-stream/14")
12239     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                  "F - test-convert-read-from-stream/15")
12240     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"          "F - test-convert-read-from-stream/16")
12241     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                 "F - test-convert-read-from-stream/17")
12242     (check-next-stream-line-equal _test-output-stream "  c3/return"                     "F - test-convert-read-from-stream/18")
12243     # . epilogue
12244     89/<- %esp 5/r32/ebp
12245     5d/pop-to-ebp
12246     c3/return
12247 
12248 test-convert-read-from-stream-with-correct-payload-size:
12249     # . prologue
12250     55/push-ebp
12251     89/<- %ebp 4/r32/esp
12252     # setup
12253     (clear-stream _test-input-stream)
12254     (clear-stream $_test-input-buffered-file->buffer)
12255     (clear-stream _test-output-stream)
12256     (clear-stream $_test-output-buffered-file->buffer)
12257     #
12258     (write _test-input-stream "fn foo {\n")
12259     (write _test-input-stream "  var s/esi: (addr stream handle int) <- copy 0\n")
12260     (write _test-input-stream "  var o/ecx: (addr handle int) <- copy 0\n")
12261     (write _test-input-stream "  read-from-stream s, o\n")
12262     (write _test-input-stream "}\n")
12263     # convert
12264     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
12265     # registers except esp clobbered at this point
12266     # restore ed
12267     89/<- %edx 4/r32/esp
12268     (flush _test-output-buffered-file)
12269     (flush _test-error-buffered-file)
12270 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
12276     # check output
12277     (check-next-stream-line-equal _test-output-stream "foo:"                            "F - test-convert-read-from-stream-with-correct-payload-size/0")
12278     (check-next-stream-line-equal _test-output-stream "  # . prologue"                  "F - test-convert-read-from-stream-with-correct-payload-size/1")
12279     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                   "F - test-convert-read-from-stream-with-correct-payload-size/2")
12280     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"          "F - test-convert-read-from-stream-with-correct-payload-size/3")
12281     (check-next-stream-line-equal _test-output-stream "  {"                             "F - test-convert-read-from-stream-with-correct-payload-size/4")
12282     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"           "F - test-convert-read-from-stream-with-correct-payload-size/5")
12283     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %esi"        "F - test-convert-read-from-stream-with-correct-payload-size/6")
12284     (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")
12285     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"        "F - test-convert-read-from-stream-with-correct-payload-size/8")
12286     (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")
12287     (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")
12288     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-read-from-stream-with-correct-payload-size/11")
12289     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %esi"         "F - test-convert-read-from-stream-with-correct-payload-size/12")
12290     (check-next-stream-line-equal _test-output-stream "  }"                             "F - test-convert-read-from-stream-with-correct-payload-size/13")
12291     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"          "F - test-convert-read-from-stream-with-correct-payload-size/14")
12292     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                  "F - test-convert-read-from-stream-with-correct-payload-size/15")
12293     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"          "F - test-convert-read-from-stream-with-correct-payload-size/16")
12294     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                 "F - test-convert-read-from-stream-with-correct-payload-size/17")
12295     (check-next-stream-line-equal _test-output-stream "  c3/return"                     "F - test-convert-read-from-stream-with-correct-payload-size/18")
12296     # . epilogue
12297     89/<- %esp 5/r32/ebp
12298     5d/pop-to-ebp
12299     c3/return
12300 
12301 test-read-from-stream-with-non-stream-atom-base-type:
12302     # . prologue
12303     55/push-ebp
12304     89/<- %ebp 4/r32/esp
12305     # setup
12306     (clear-stream _test-input-stream)
12307     (clear-stream $_test-input-buffered-file->buffer)
12308     (clear-stream _test-output-stream)
12309     (clear-stream $_test-output-buffered-file->buffer)
12310     (clear-stream _test-error-stream)
12311     (clear-stream $_test-error-buffered-file->buffer)
12312     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12313     68/push 0/imm32
12314     68/push 0/imm32
12315     89/<- %edx 4/r32/esp
12316     (tailor-exit-descriptor %edx 0x10)
12317     #
12318     (write _test-input-stream "fn foo {\n")
12319     (write _test-input-stream "  var a: int\n")
12320     (write _test-input-stream "  read-from-stream a, 0\n")
12321     (write _test-input-stream "}\n")
12322     # convert
12323     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12324     # registers except esp clobbered at this point
12325     # restore ed
12326     89/<- %edx 4/r32/esp
12327     (flush _test-output-buffered-file)
12328     (flush _test-error-buffered-file)
12329 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12335     # check output
12336     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-non-stream-atom-base-type: output should be empty")
12337     (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")
12338     # check that stop(1) was called
12339     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-non-stream-atom-base-type: exit status")
12340     # don't restore from ebp
12341     81 0/subop/add %esp 8/imm32
12342     # . epilogue
12343     5d/pop-to-ebp
12344     c3/return
12345 
12346 test-read-from-stream-with-non-stream-compound-base-type:
12347     # . prologue
12348     55/push-ebp
12349     89/<- %ebp 4/r32/esp
12350     # setup
12351     (clear-stream _test-input-stream)
12352     (clear-stream $_test-input-buffered-file->buffer)
12353     (clear-stream _test-output-stream)
12354     (clear-stream $_test-output-buffered-file->buffer)
12355     (clear-stream _test-error-stream)
12356     (clear-stream $_test-error-buffered-file->buffer)
12357     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12358     68/push 0/imm32
12359     68/push 0/imm32
12360     89/<- %edx 4/r32/esp
12361     (tailor-exit-descriptor %edx 0x10)
12362     #
12363     (write _test-input-stream "fn foo {\n")
12364     (write _test-input-stream "  var a: (handle int)\n")
12365     (write _test-input-stream "  read-from-stream a, 0\n")
12366     (write _test-input-stream "}\n")
12367     # convert
12368     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12369     # registers except esp clobbered at this point
12370     # restore ed
12371     89/<- %edx 4/r32/esp
12372     (flush _test-output-buffered-file)
12373     (flush _test-error-buffered-file)
12374 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12380     # check output
12381     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-non-stream-compound-base-type: output should be empty")
12382     (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")
12383     # check that stop(1) was called
12384     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-non-stream-compound-base-type: exit status")
12385     # don't restore from ebp
12386     81 0/subop/add %esp 8/imm32
12387     # . epilogue
12388     5d/pop-to-ebp
12389     c3/return
12390 
12391 test-read-from-stream-with-non-stream-compound-base-type-2:
12392     # . prologue
12393     55/push-ebp
12394     89/<- %ebp 4/r32/esp
12395     # setup
12396     (clear-stream _test-input-stream)
12397     (clear-stream $_test-input-buffered-file->buffer)
12398     (clear-stream _test-output-stream)
12399     (clear-stream $_test-output-buffered-file->buffer)
12400     (clear-stream _test-error-stream)
12401     (clear-stream $_test-error-buffered-file->buffer)
12402     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12403     68/push 0/imm32
12404     68/push 0/imm32
12405     89/<- %edx 4/r32/esp
12406     (tailor-exit-descriptor %edx 0x10)
12407     #
12408     (write _test-input-stream "fn foo {\n")
12409     (write _test-input-stream "  var a: (addr int)\n")
12410     (write _test-input-stream "  read-from-stream a, 0\n")
12411     (write _test-input-stream "}\n")
12412     # convert
12413     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12414     # registers except esp clobbered at this point
12415     # restore ed
12416     89/<- %edx 4/r32/esp
12417     (flush _test-output-buffered-file)
12418     (flush _test-error-buffered-file)
12419 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12425     # check output
12426     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-non-stream-compound-base-type-2: output should be empty")
12427     (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")
12428     # check that stop(1) was called
12429     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-non-stream-compound-base-type-2: exit status")
12430     # don't restore from ebp
12431     81 0/subop/add %esp 8/imm32
12432     # . epilogue
12433     5d/pop-to-ebp
12434     c3/return
12435 
12436 test-read-from-stream-with-stream-atom-base-type:
12437     # . prologue
12438     55/push-ebp
12439     89/<- %ebp 4/r32/esp
12440     # setup
12441     (clear-stream _test-input-stream)
12442     (clear-stream $_test-input-buffered-file->buffer)
12443     (clear-stream _test-output-stream)
12444     (clear-stream $_test-output-buffered-file->buffer)
12445     (clear-stream _test-error-stream)
12446     (clear-stream $_test-error-buffered-file->buffer)
12447     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12448     68/push 0/imm32
12449     68/push 0/imm32
12450     89/<- %edx 4/r32/esp
12451     (tailor-exit-descriptor %edx 0x10)
12452     #
12453     (write _test-input-stream "fn foo {\n")
12454     (write _test-input-stream "  var a: stream\n")
12455     (write _test-input-stream "  read-from-stream a, 0\n")
12456     (write _test-input-stream "}\n")
12457     # convert
12458     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12459     # registers except esp clobbered at this point
12460     # restore ed
12461     89/<- %edx 4/r32/esp
12462     (flush _test-output-buffered-file)
12463     (flush _test-error-buffered-file)
12464 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12470     # check output
12471     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-stream-atom-base-type: output should be empty")
12472     (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")
12473     # check that stop(1) was called
12474     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-stream-atom-base-type: exit status")
12475     # don't restore from ebp
12476     81 0/subop/add %esp 8/imm32
12477     # . epilogue
12478     5d/pop-to-ebp
12479     c3/return
12480 
12481 test-read-from-stream-with-wrong-index-type:
12482     # . prologue
12483     55/push-ebp
12484     89/<- %ebp 4/r32/esp
12485     # setup
12486     (clear-stream _test-input-stream)
12487     (clear-stream $_test-input-buffered-file->buffer)
12488     (clear-stream _test-output-stream)
12489     (clear-stream $_test-output-buffered-file->buffer)
12490     (clear-stream _test-error-stream)
12491     (clear-stream $_test-error-buffered-file->buffer)
12492     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12493     68/push 0/imm32
12494     68/push 0/imm32
12495     89/<- %edx 4/r32/esp
12496     (tailor-exit-descriptor %edx 0x10)
12497     #
12498     (write _test-input-stream "fn foo {\n")
12499     (write _test-input-stream "  var a/eax: (addr stream int) <- copy 0\n")
12500     (write _test-input-stream "  var b: boolean\n")
12501     (write _test-input-stream "  read-from-stream a, b\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-read-from-stream-with-wrong-index-type: output should be empty")
12518     (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")
12519     # check that stop(1) was called
12520     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-wrong-index-type: 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-read-from-stream-with-no-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 "  read-from-stream\n")
12546     (write _test-input-stream "}\n")
12547     # convert
12548     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12549     # registers except esp clobbered at this point
12550     # restore ed
12551     89/<- %edx 4/r32/esp
12552     (flush _test-output-buffered-file)
12553     (flush _test-error-buffered-file)
12554 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12560     # check output
12561     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-no-inouts: output should be empty")
12562     (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")
12563     # check that stop(1) was called
12564     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-no-inouts: exit status")
12565     # don't restore from ebp
12566     81 0/subop/add %esp 8/imm32
12567     # . epilogue
12568     5d/pop-to-ebp
12569     c3/return
12570 
12571 test-read-from-stream-with-too-few-inouts:
12572     # . prologue
12573     55/push-ebp
12574     89/<- %ebp 4/r32/esp
12575     # setup
12576     (clear-stream _test-input-stream)
12577     (clear-stream $_test-input-buffered-file->buffer)
12578     (clear-stream _test-output-stream)
12579     (clear-stream $_test-output-buffered-file->buffer)
12580     (clear-stream _test-error-stream)
12581     (clear-stream $_test-error-buffered-file->buffer)
12582     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12583     68/push 0/imm32
12584     68/push 0/imm32
12585     89/<- %edx 4/r32/esp
12586     (tailor-exit-descriptor %edx 0x10)
12587     #
12588     (write _test-input-stream "fn foo {\n")
12589     (write _test-input-stream "  var a: (addr stream int)\n")
12590     (write _test-input-stream "  read-from-stream a\n")
12591     (write _test-input-stream "}\n")
12592     # convert
12593     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12594     # registers except esp clobbered at this point
12595     # restore ed
12596     89/<- %edx 4/r32/esp
12597     (flush _test-output-buffered-file)
12598     (flush _test-error-buffered-file)
12599 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12605     # check output
12606     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-too-few-inouts: output should be empty")
12607     (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")
12608     # check that stop(1) was called
12609     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-too-few-inouts: exit status")
12610     # don't restore from ebp
12611     81 0/subop/add %esp 8/imm32
12612     # . epilogue
12613     5d/pop-to-ebp
12614     c3/return
12615 
12616 test-read-from-stream-with-too-many-inouts:
12617     # . prologue
12618     55/push-ebp
12619     89/<- %ebp 4/r32/esp
12620     # setup
12621     (clear-stream _test-input-stream)
12622     (clear-stream $_test-input-buffered-file->buffer)
12623     (clear-stream _test-output-stream)
12624     (clear-stream $_test-output-buffered-file->buffer)
12625     (clear-stream _test-error-stream)
12626     (clear-stream $_test-error-buffered-file->buffer)
12627     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12628     68/push 0/imm32
12629     68/push 0/imm32
12630     89/<- %edx 4/r32/esp
12631     (tailor-exit-descriptor %edx 0x10)
12632     #
12633     (write _test-input-stream "fn foo {\n")
12634     (write _test-input-stream "  var a: (addr stream int)\n")
12635     (write _test-input-stream "  var b: (addr int)\n")
12636     (write _test-input-stream "  read-from-stream a, b, 0\n")
12637     (write _test-input-stream "}\n")
12638     # convert
12639     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12640     # registers except esp clobbered at this point
12641     # restore ed
12642     89/<- %edx 4/r32/esp
12643     (flush _test-output-buffered-file)
12644     (flush _test-error-buffered-file)
12645 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12651     # check output
12652     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-too-many-inouts: output should be empty")
12653     (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")
12654     # check that stop(1) was called
12655     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-too-many-inouts: exit status")
12656     # don't restore from ebp
12657     81 0/subop/add %esp 8/imm32
12658     # . epilogue
12659     5d/pop-to-ebp
12660     c3/return
12661 
12662 test-read-from-stream-with-output:
12663     # . prologue
12664     55/push-ebp
12665     89/<- %ebp 4/r32/esp
12666     # setup
12667     (clear-stream _test-input-stream)
12668     (clear-stream $_test-input-buffered-file->buffer)
12669     (clear-stream _test-output-stream)
12670     (clear-stream $_test-output-buffered-file->buffer)
12671     (clear-stream _test-error-stream)
12672     (clear-stream $_test-error-buffered-file->buffer)
12673     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12674     68/push 0/imm32
12675     68/push 0/imm32
12676     89/<- %edx 4/r32/esp
12677     (tailor-exit-descriptor %edx 0x10)
12678     #
12679     (write _test-input-stream "fn foo {\n")
12680     (write _test-input-stream "  var a: (addr stream int)\n")
12681     (write _test-input-stream "  var b/eax: (addr int) <- copy 0\n")
12682     (write _test-input-stream "  b <- read-from-stream a, b\n")
12683     (write _test-input-stream "}\n")
12684     # convert
12685     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12686     # registers except esp clobbered at this point
12687     # restore ed
12688     89/<- %edx 4/r32/esp
12689     (flush _test-output-buffered-file)
12690     (flush _test-error-buffered-file)
12691 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12697     # check output
12698     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-output: output should be empty")
12699     (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")
12700     # check that stop(1) was called
12701     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-output: exit status")
12702     # don't restore from ebp
12703     81 0/subop/add %esp 8/imm32
12704     # . epilogue
12705     5d/pop-to-ebp
12706     c3/return
12707 
12708 test-convert-write-to-stream:
12709     # . prologue
12710     55/push-ebp
12711     89/<- %ebp 4/r32/esp
12712     # setup
12713     (clear-stream _test-input-stream)
12714     (clear-stream $_test-input-buffered-file->buffer)
12715     (clear-stream _test-output-stream)
12716     (clear-stream $_test-output-buffered-file->buffer)
12717     #
12718     (write _test-input-stream "fn foo {\n")
12719     (write _test-input-stream "  var s/esi: (addr stream int) <- copy 0\n")
12720     (write _test-input-stream "  var o/ecx: (addr int) <- copy 0\n")
12721     (write _test-input-stream "  write-to-stream s, o\n")
12722     (write _test-input-stream "}\n")
12723     # convert
12724     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
12725     # registers except esp clobbered at this point
12726     # restore ed
12727     89/<- %edx 4/r32/esp
12728     (flush _test-output-buffered-file)
12729     (flush _test-error-buffered-file)
12730 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
12736     # check output
12737     (check-next-stream-line-equal _test-output-stream "foo:"                            "F - test-convert-write-to-stream/0")
12738     (check-next-stream-line-equal _test-output-stream "  # . prologue"                  "F - test-convert-write-to-stream/1")
12739     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                   "F - test-convert-write-to-stream/2")
12740     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"          "F - test-convert-write-to-stream/3")
12741     (check-next-stream-line-equal _test-output-stream "  {"                             "F - test-convert-write-to-stream/4")
12742     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"           "F - test-convert-write-to-stream/5")
12743     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %esi"        "F - test-convert-write-to-stream/6")
12744     (check-next-stream-line-equal _test-output-stream "    be/copy-to-esi 0/imm32"      "F - test-convert-write-to-stream/7")
12745     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"        "F - test-convert-write-to-stream/8")
12746     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"      "F - test-convert-write-to-stream/9")
12747     (check-next-stream-line-equal _test-output-stream "    (write-to-stream %esi %ecx 0x00000004)"  "F - test-convert-write-to-stream/10")
12748     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-write-to-stream/11")
12749     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %esi"         "F - test-convert-write-to-stream/12")
12750     (check-next-stream-line-equal _test-output-stream "  }"                             "F - test-convert-write-to-stream/13")
12751     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"          "F - test-convert-write-to-stream/14")
12752     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                  "F - test-convert-write-to-stream/15")
12753     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"          "F - test-convert-write-to-stream/16")
12754     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                 "F - test-convert-write-to-stream/17")
12755     (check-next-stream-line-equal _test-output-stream "  c3/return"                     "F - test-convert-write-to-stream/18")
12756     # . epilogue
12757     89/<- %esp 5/r32/ebp
12758     5d/pop-to-ebp
12759     c3/return
12760 
12761 test-convert-write-to-stream-with-correct-payload-size:
12762     # . prologue
12763     55/push-ebp
12764     89/<- %ebp 4/r32/esp
12765     # setup
12766     (clear-stream _test-input-stream)
12767     (clear-stream $_test-input-buffered-file->buffer)
12768     (clear-stream _test-output-stream)
12769     (clear-stream $_test-output-buffered-file->buffer)
12770     #
12771     (write _test-input-stream "fn foo {\n")
12772     (write _test-input-stream "  var s/esi: (addr stream handle int) <- copy 0\n")
12773     (write _test-input-stream "  var o/ecx: (addr handle int) <- copy 0\n")
12774     (write _test-input-stream "  write-to-stream s, o\n")
12775     (write _test-input-stream "}\n")
12776     # convert
12777     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
12778     # registers except esp clobbered at this point
12779     # restore ed
12780     89/<- %edx 4/r32/esp
12781     (flush _test-output-buffered-file)
12782     (flush _test-error-buffered-file)
12783 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
12789     # check output
12790     (check-next-stream-line-equal _test-output-stream "foo:"                            "F - test-convert-write-to-stream-with-correct-payload-size/0")
12791     (check-next-stream-line-equal _test-output-stream "  # . prologue"                  "F - test-convert-write-to-stream-with-correct-payload-size/1")
12792     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                   "F - test-convert-write-to-stream-with-correct-payload-size/2")
12793     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"          "F - test-convert-write-to-stream-with-correct-payload-size/3")
12794     (check-next-stream-line-equal _test-output-stream "  {"                             "F - test-convert-write-to-stream-with-correct-payload-size/4")
12795     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"           "F - test-convert-write-to-stream-with-correct-payload-size/5")
12796     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %esi"        "F - test-convert-write-to-stream-with-correct-payload-size/6")
12797     (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")
12798     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"        "F - test-convert-write-to-stream-with-correct-payload-size/8")
12799     (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")
12800     (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")
12801     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-write-to-stream-with-correct-payload-size/11")
12802     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %esi"         "F - test-convert-write-to-stream-with-correct-payload-size/12")
12803     (check-next-stream-line-equal _test-output-stream "  }"                             "F - test-convert-write-to-stream-with-correct-payload-size/13")
12804     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"          "F - test-convert-write-to-stream-with-correct-payload-size/14")
12805     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                  "F - test-convert-write-to-stream-with-correct-payload-size/15")
12806     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"          "F - test-convert-write-to-stream-with-correct-payload-size/16")
12807     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                 "F - test-convert-write-to-stream-with-correct-payload-size/17")
12808     (check-next-stream-line-equal _test-output-stream "  c3/return"                     "F - test-convert-write-to-stream-with-correct-payload-size/18")
12809     # . epilogue
12810     89/<- %esp 5/r32/ebp
12811     5d/pop-to-ebp
12812     c3/return
12813 
12814 test-write-to-stream-with-non-stream-atom-base-type:
12815     # . prologue
12816     55/push-ebp
12817     89/<- %ebp 4/r32/esp
12818     # setup
12819     (clear-stream _test-input-stream)
12820     (clear-stream $_test-input-buffered-file->buffer)
12821     (clear-stream _test-output-stream)
12822     (clear-stream $_test-output-buffered-file->buffer)
12823     (clear-stream _test-error-stream)
12824     (clear-stream $_test-error-buffered-file->buffer)
12825     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12826     68/push 0/imm32
12827     68/push 0/imm32
12828     89/<- %edx 4/r32/esp
12829     (tailor-exit-descriptor %edx 0x10)
12830     #
12831     (write _test-input-stream "fn foo {\n")
12832     (write _test-input-stream "  var a: int\n")
12833     (write _test-input-stream "  write-to-stream a, 0\n")
12834     (write _test-input-stream "}\n")
12835     # convert
12836     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12837     # registers except esp clobbered at this point
12838     # restore ed
12839     89/<- %edx 4/r32/esp
12840     (flush _test-output-buffered-file)
12841     (flush _test-error-buffered-file)
12842 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12848     # check output
12849     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-non-stream-atom-base-type: output should be empty")
12850     (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")
12851     # check that stop(1) was called
12852     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-non-stream-atom-base-type: exit status")
12853     # don't restore from ebp
12854     81 0/subop/add %esp 8/imm32
12855     # . epilogue
12856     5d/pop-to-ebp
12857     c3/return
12858 
12859 test-write-to-stream-with-non-stream-compound-base-type:
12860     # . prologue
12861     55/push-ebp
12862     89/<- %ebp 4/r32/esp
12863     # setup
12864     (clear-stream _test-input-stream)
12865     (clear-stream $_test-input-buffered-file->buffer)
12866     (clear-stream _test-output-stream)
12867     (clear-stream $_test-output-buffered-file->buffer)
12868     (clear-stream _test-error-stream)
12869     (clear-stream $_test-error-buffered-file->buffer)
12870     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12871     68/push 0/imm32
12872     68/push 0/imm32
12873     89/<- %edx 4/r32/esp
12874     (tailor-exit-descriptor %edx 0x10)
12875     #
12876     (write _test-input-stream "fn foo {\n")
12877     (write _test-input-stream "  var a: (handle int)\n")
12878     (write _test-input-stream "  write-to-stream a, 0\n")
12879     (write _test-input-stream "}\n")
12880     # convert
12881     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12882     # registers except esp clobbered at this point
12883     # restore ed
12884     89/<- %edx 4/r32/esp
12885     (flush _test-output-buffered-file)
12886     (flush _test-error-buffered-file)
12887 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12893     # check output
12894     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-non-stream-compound-base-type: output should be empty")
12895     (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")
12896     # check that stop(1) was called
12897     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-non-stream-compound-base-type: exit status")
12898     # don't restore from ebp
12899     81 0/subop/add %esp 8/imm32
12900     # . epilogue
12901     5d/pop-to-ebp
12902     c3/return
12903 
12904 test-write-to-stream-with-non-stream-compound-base-type-2:
12905     # . prologue
12906     55/push-ebp
12907     89/<- %ebp 4/r32/esp
12908     # setup
12909     (clear-stream _test-input-stream)
12910     (clear-stream $_test-input-buffered-file->buffer)
12911     (clear-stream _test-output-stream)
12912     (clear-stream $_test-output-buffered-file->buffer)
12913     (clear-stream _test-error-stream)
12914     (clear-stream $_test-error-buffered-file->buffer)
12915     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12916     68/push 0/imm32
12917     68/push 0/imm32
12918     89/<- %edx 4/r32/esp
12919     (tailor-exit-descriptor %edx 0x10)
12920     #
12921     (write _test-input-stream "fn foo {\n")
12922     (write _test-input-stream "  var a: (addr int)\n")
12923     (write _test-input-stream "  write-to-stream a, 0\n")
12924     (write _test-input-stream "}\n")
12925     # convert
12926     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12927     # registers except esp clobbered at this point
12928     # restore ed
12929     89/<- %edx 4/r32/esp
12930     (flush _test-output-buffered-file)
12931     (flush _test-error-buffered-file)
12932 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12938     # check output
12939     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-non-stream-compound-base-type-2: output should be empty")
12940     (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")
12941     # check that stop(1) was called
12942     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-non-stream-compound-base-type-2: exit status")
12943     # don't restore from ebp
12944     81 0/subop/add %esp 8/imm32
12945     # . epilogue
12946     5d/pop-to-ebp
12947     c3/return
12948 
12949 test-write-to-stream-with-stream-atom-base-type:
12950     # . prologue
12951     55/push-ebp
12952     89/<- %ebp 4/r32/esp
12953     # setup
12954     (clear-stream _test-input-stream)
12955     (clear-stream $_test-input-buffered-file->buffer)
12956     (clear-stream _test-output-stream)
12957     (clear-stream $_test-output-buffered-file->buffer)
12958     (clear-stream _test-error-stream)
12959     (clear-stream $_test-error-buffered-file->buffer)
12960     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12961     68/push 0/imm32
12962     68/push 0/imm32
12963     89/<- %edx 4/r32/esp
12964     (tailor-exit-descriptor %edx 0x10)
12965     #
12966     (write _test-input-stream "fn foo {\n")
12967     (write _test-input-stream "  var a: stream\n")
12968     (write _test-input-stream "  write-to-stream a, 0\n")
12969     (write _test-input-stream "}\n")
12970     # convert
12971     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12972     # registers except esp clobbered at this point
12973     # restore ed
12974     89/<- %edx 4/r32/esp
12975     (flush _test-output-buffered-file)
12976     (flush _test-error-buffered-file)
12977 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12983     # check output
12984     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-stream-atom-base-type: output should be empty")
12985     (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")
12986     # check that stop(1) was called
12987     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-stream-atom-base-type: exit status")
12988     # don't restore from ebp
12989     81 0/subop/add %esp 8/imm32
12990     # . epilogue
12991     5d/pop-to-ebp
12992     c3/return
12993 
12994 test-write-to-stream-with-wrong-index-type:
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 "  var a/eax: (addr stream int) <- copy 0\n")
13013     (write _test-input-stream "  var b: boolean\n")
13014     (write _test-input-stream "  write-to-stream a, b\n")
13015     (write _test-input-stream "}\n")
13016     # convert
13017     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13018     # registers except esp clobbered at this point
13019     # restore ed
13020     89/<- %edx 4/r32/esp
13021     (flush _test-output-buffered-file)
13022     (flush _test-error-buffered-file)
13023 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13029     # check output
13030     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-wrong-index-type: output should be empty")
13031     (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")
13032     # check that stop(1) was called
13033     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-wrong-index-type: exit status")
13034     # don't restore from ebp
13035     81 0/subop/add %esp 8/imm32
13036     # . epilogue
13037     5d/pop-to-ebp
13038     c3/return
13039 
13040 test-write-to-stream-with-no-inouts:
13041     # . prologue
13042     55/push-ebp
13043     89/<- %ebp 4/r32/esp
13044     # setup
13045     (clear-stream _test-input-stream)
13046     (clear-stream $_test-input-buffered-file->buffer)
13047     (clear-stream _test-output-stream)
13048     (clear-stream $_test-output-buffered-file->buffer)
13049     (clear-stream _test-error-stream)
13050     (clear-stream $_test-error-buffered-file->buffer)
13051     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13052     68/push 0/imm32
13053     68/push 0/imm32
13054     89/<- %edx 4/r32/esp
13055     (tailor-exit-descriptor %edx 0x10)
13056     #
13057     (write _test-input-stream "fn foo {\n")
13058     (write _test-input-stream "  write-to-stream\n")
13059     (write _test-input-stream "}\n")
13060     # convert
13061     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13062     # registers except esp clobbered at this point
13063     # restore ed
13064     89/<- %edx 4/r32/esp
13065     (flush _test-output-buffered-file)
13066     (flush _test-error-buffered-file)
13067 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13073     # check output
13074     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-no-inouts: output should be empty")
13075     (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")
13076     # check that stop(1) was called
13077     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-no-inouts: exit status")
13078     # don't restore from ebp
13079     81 0/subop/add %esp 8/imm32
13080     # . epilogue
13081     5d/pop-to-ebp
13082     c3/return
13083 
13084 test-write-to-stream-with-too-few-inouts:
13085     # . prologue
13086     55/push-ebp
13087     89/<- %ebp 4/r32/esp
13088     # setup
13089     (clear-stream _test-input-stream)
13090     (clear-stream $_test-input-buffered-file->buffer)
13091     (clear-stream _test-output-stream)
13092     (clear-stream $_test-output-buffered-file->buffer)
13093     (clear-stream _test-error-stream)
13094     (clear-stream $_test-error-buffered-file->buffer)
13095     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13096     68/push 0/imm32
13097     68/push 0/imm32
13098     89/<- %edx 4/r32/esp
13099     (tailor-exit-descriptor %edx 0x10)
13100     #
13101     (write _test-input-stream "fn foo {\n")
13102     (write _test-input-stream "  var a: (addr stream int)\n")
13103     (write _test-input-stream "  write-to-stream a\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-write-to-stream-with-too-few-inouts: output should be empty")
13120     (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")
13121     # check that stop(1) was called
13122     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-too-few-inouts: 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-write-to-stream-with-too-many-inouts:
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 a: (addr stream int)\n")
13148     (write _test-input-stream "  var b: (addr int)\n")
13149     (write _test-input-stream "  write-to-stream a, b, 0\n")
13150     (write _test-input-stream "}\n")
13151     # convert
13152     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13153     # registers except esp clobbered at this point
13154     # restore ed
13155     89/<- %edx 4/r32/esp
13156     (flush _test-output-buffered-file)
13157     (flush _test-error-buffered-file)
13158 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13164     # check output
13165     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-too-many-inouts: output should be empty")
13166     (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")
13167     # check that stop(1) was called
13168     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-too-many-inouts: exit status")
13169     # don't restore from ebp
13170     81 0/subop/add %esp 8/imm32
13171     # . epilogue
13172     5d/pop-to-ebp
13173     c3/return
13174 
13175 test-write-to-stream-with-output:
13176     # . prologue
13177     55/push-ebp
13178     89/<- %ebp 4/r32/esp
13179     # setup
13180     (clear-stream _test-input-stream)
13181     (clear-stream $_test-input-buffered-file->buffer)
13182     (clear-stream _test-output-stream)
13183     (clear-stream $_test-output-buffered-file->buffer)
13184     (clear-stream _test-error-stream)
13185     (clear-stream $_test-error-buffered-file->buffer)
13186     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13187     68/push 0/imm32
13188     68/push 0/imm32
13189     89/<- %edx 4/r32/esp
13190     (tailor-exit-descriptor %edx 0x10)
13191     #
13192     (write _test-input-stream "fn foo {\n")
13193     (write _test-input-stream "  var a: (addr stream int)\n")
13194     (write _test-input-stream "  var b/eax: (addr int) <- copy 0\n")
13195     (write _test-input-stream "  b <- write-to-stream a, b\n")
13196     (write _test-input-stream "}\n")
13197     # convert
13198     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13199     # registers except esp clobbered at this point
13200     # restore ed
13201     89/<- %edx 4/r32/esp
13202     (flush _test-output-buffered-file)
13203     (flush _test-error-buffered-file)
13204 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13210     # check output
13211     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-output: output should be empty")
13212     (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")
13213     # check that stop(1) was called
13214     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-output: exit status")
13215     # don't restore from ebp
13216     81 0/subop/add %esp 8/imm32
13217     # . epilogue
13218     5d/pop-to-ebp
13219     c3/return
13220 
13221 test-length-with-non-array-atom-base-type:
13222     # . prologue
13223     55/push-ebp
13224     89/<- %ebp 4/r32/esp
13225     # setup
13226     (clear-stream _test-input-stream)
13227     (clear-stream $_test-input-buffered-file->buffer)
13228     (clear-stream _test-output-stream)
13229     (clear-stream $_test-output-buffered-file->buffer)
13230     (clear-stream _test-error-stream)
13231     (clear-stream $_test-error-buffered-file->buffer)
13232     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13233     68/push 0/imm32
13234     68/push 0/imm32
13235     89/<- %edx 4/r32/esp
13236     (tailor-exit-descriptor %edx 0x10)
13237     #
13238     (write _test-input-stream "fn foo {\n")
13239     (write _test-input-stream "  var a: int\n")
13240     (write _test-input-stream "  var c/ecx: int <- length a\n")
13241     (write _test-input-stream "}\n")
13242     # convert
13243     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13244     # registers except esp clobbered at this point
13245     # restore ed
13246     89/<- %edx 4/r32/esp
13247     (flush _test-output-buffered-file)
13248     (flush _test-error-buffered-file)
13249 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13255     # check output
13256     (check-stream-equal _test-output-stream  ""  "F - test-length-with-non-array-atom-base-type: output should be empty")
13257     (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")
13258     # check that stop(1) was called
13259     (check-ints-equal *(edx+4) 2 "F - test-length-with-non-array-atom-base-type: exit status")
13260     # don't restore from ebp
13261     81 0/subop/add %esp 8/imm32
13262     # . epilogue
13263     5d/pop-to-ebp
13264     c3/return
13265 
13266 test-length-with-non-array-compound-base-type:
13267     # . prologue
13268     55/push-ebp
13269     89/<- %ebp 4/r32/esp
13270     # setup
13271     (clear-stream _test-input-stream)
13272     (clear-stream $_test-input-buffered-file->buffer)
13273     (clear-stream _test-output-stream)
13274     (clear-stream $_test-output-buffered-file->buffer)
13275     (clear-stream _test-error-stream)
13276     (clear-stream $_test-error-buffered-file->buffer)
13277     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13278     68/push 0/imm32
13279     68/push 0/imm32
13280     89/<- %edx 4/r32/esp
13281     (tailor-exit-descriptor %edx 0x10)
13282     #
13283     (write _test-input-stream "fn foo {\n")
13284     (write _test-input-stream "  var a: (handle int)\n")
13285     (write _test-input-stream "  var c/ecx: (addr int) <- length a, 0\n")
13286     (write _test-input-stream "}\n")
13287     # convert
13288     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13289     # registers except esp clobbered at this point
13290     # restore ed
13291     89/<- %edx 4/r32/esp
13292     (flush _test-output-buffered-file)
13293     (flush _test-error-buffered-file)
13294 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13300     # check output
13301     (check-stream-equal _test-output-stream  ""  "F - test-length-with-non-array-compound-base-type: output should be empty")
13302     (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")
13303     # check that stop(1) was called
13304     (check-ints-equal *(edx+4) 2 "F - test-length-with-non-array-compound-base-type: exit status")
13305     # don't restore from ebp
13306     81 0/subop/add %esp 8/imm32
13307     # . epilogue
13308     5d/pop-to-ebp
13309     c3/return
13310 
13311 test-length-with-non-array-compound-base-type-2:
13312     # . prologue
13313     55/push-ebp
13314     89/<- %ebp 4/r32/esp
13315     # setup
13316     (clear-stream _test-input-stream)
13317     (clear-stream $_test-input-buffered-file->buffer)
13318     (clear-stream _test-output-stream)
13319     (clear-stream $_test-output-buffered-file->buffer)
13320     (clear-stream _test-error-stream)
13321     (clear-stream $_test-error-buffered-file->buffer)
13322     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13323     68/push 0/imm32
13324     68/push 0/imm32
13325     89/<- %edx 4/r32/esp
13326     (tailor-exit-descriptor %edx 0x10)
13327     #
13328     (write _test-input-stream "fn foo {\n")
13329     (write _test-input-stream "  var a: (addr int)\n")
13330     (write _test-input-stream "  var c/ecx: (addr int) <- length a, 0\n")
13331     (write _test-input-stream "}\n")
13332     # convert
13333     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13334     # registers except esp clobbered at this point
13335     # restore ed
13336     89/<- %edx 4/r32/esp
13337     (flush _test-output-buffered-file)
13338     (flush _test-error-buffered-file)
13339 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13345     # check output
13346     (check-stream-equal _test-output-stream  ""  "F - test-length-with-non-array-compound-base-type-2: output should be empty")
13347     (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")
13348     # check that stop(1) was called
13349     (check-ints-equal *(edx+4) 2 "F - test-length-with-non-array-compound-base-type-2: exit status")
13350     # don't restore from ebp
13351     81 0/subop/add %esp 8/imm32
13352     # . epilogue
13353     5d/pop-to-ebp
13354     c3/return
13355 
13356 test-length-with-array-atom-base-type:
13357     # . prologue
13358     55/push-ebp
13359     89/<- %ebp 4/r32/esp
13360     # setup
13361     (clear-stream _test-input-stream)
13362     (clear-stream $_test-input-buffered-file->buffer)
13363     (clear-stream _test-output-stream)
13364     (clear-stream $_test-output-buffered-file->buffer)
13365     (clear-stream _test-error-stream)
13366     (clear-stream $_test-error-buffered-file->buffer)
13367     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13368     68/push 0/imm32
13369     68/push 0/imm32
13370     89/<- %edx 4/r32/esp
13371     (tailor-exit-descriptor %edx 0x10)
13372     #
13373     (write _test-input-stream "fn foo {\n")
13374     (write _test-input-stream "  var a: array\n")
13375     (write _test-input-stream "  var c/ecx: (addr int) <- length a\n")
13376     (write _test-input-stream "}\n")
13377     # convert
13378     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13379     # registers except esp clobbered at this point
13380     # restore ed
13381     89/<- %edx 4/r32/esp
13382     (flush _test-output-buffered-file)
13383     (flush _test-error-buffered-file)
13384 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13390     # check output
13391     (check-stream-equal _test-output-stream  ""  "F - test-length-with-array-atom-base-type: output should be empty")
13392     (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")
13393     # check that stop(1) was called
13394     (check-ints-equal *(edx+4) 2 "F - test-length-with-array-atom-base-type: exit status")
13395     # don't restore from ebp
13396     81 0/subop/add %esp 8/imm32
13397     # . epilogue
13398     5d/pop-to-ebp
13399     c3/return
13400 
13401 test-length-with-addr-base-on-stack:
13402     # . prologue
13403     55/push-ebp
13404     89/<- %ebp 4/r32/esp
13405     # setup
13406     (clear-stream _test-input-stream)
13407     (clear-stream $_test-input-buffered-file->buffer)
13408     (clear-stream _test-output-stream)
13409     (clear-stream $_test-output-buffered-file->buffer)
13410     (clear-stream _test-error-stream)
13411     (clear-stream $_test-error-buffered-file->buffer)
13412     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13413     68/push 0/imm32
13414     68/push 0/imm32
13415     89/<- %edx 4/r32/esp
13416     (tailor-exit-descriptor %edx 0x10)
13417     #
13418     (write _test-input-stream "fn foo {\n")
13419     (write _test-input-stream "  var a: (addr array int)\n")
13420     (write _test-input-stream "  var c/ecx: (addr int) <- length a\n")
13421     (write _test-input-stream "}\n")
13422     # convert
13423     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13424     # registers except esp clobbered at this point
13425     # restore ed
13426     89/<- %edx 4/r32/esp
13427     (flush _test-output-buffered-file)
13428     (flush _test-error-buffered-file)
13429 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13435     # check output
13436     (check-stream-equal _test-output-stream  ""  "F - test-length-with-addr-base-on-stack: output should be empty")
13437     (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")
13438     # check that stop(1) was called
13439     (check-ints-equal *(edx+4) 2 "F - test-length-with-addr-base-on-stack: exit status")
13440     # don't restore from ebp
13441     81 0/subop/add %esp 8/imm32
13442     # . epilogue
13443     5d/pop-to-ebp
13444     c3/return
13445 
13446 test-length-with-wrong-output-type:
13447     # . prologue
13448     55/push-ebp
13449     89/<- %ebp 4/r32/esp
13450     # setup
13451     (clear-stream _test-input-stream)
13452     (clear-stream $_test-input-buffered-file->buffer)
13453     (clear-stream _test-output-stream)
13454     (clear-stream $_test-output-buffered-file->buffer)
13455     (clear-stream _test-error-stream)
13456     (clear-stream $_test-error-buffered-file->buffer)
13457     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13458     68/push 0/imm32
13459     68/push 0/imm32
13460     89/<- %edx 4/r32/esp
13461     (tailor-exit-descriptor %edx 0x10)
13462     #
13463     (write _test-input-stream "fn foo {\n")
13464     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
13465     (write _test-input-stream "  var o/edi: (addr int) <- length a\n")
13466     (write _test-input-stream "}\n")
13467     # convert
13468     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13469     # registers except esp clobbered at this point
13470     # restore ed
13471     89/<- %edx 4/r32/esp
13472     (flush _test-output-buffered-file)
13473     (flush _test-error-buffered-file)
13474 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13480     # check output
13481     (check-stream-equal _test-output-stream  ""  "F - test-length-with-wrong-output-type: output should be empty")
13482     (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")
13483     # check that stop(1) was called
13484     (check-ints-equal *(edx+4) 2 "F - test-length-with-wrong-output-type: exit status")
13485     # don't restore from ebp
13486     81 0/subop/add %esp 8/imm32
13487     # . epilogue
13488     5d/pop-to-ebp
13489     c3/return
13490 
13491 test-length-with-wrong-output-compound-type:
13492     # . prologue
13493     55/push-ebp
13494     89/<- %ebp 4/r32/esp
13495     # setup
13496     (clear-stream _test-input-stream)
13497     (clear-stream $_test-input-buffered-file->buffer)
13498     (clear-stream _test-output-stream)
13499     (clear-stream $_test-output-buffered-file->buffer)
13500     (clear-stream _test-error-stream)
13501     (clear-stream $_test-error-buffered-file->buffer)
13502     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13503     68/push 0/imm32
13504     68/push 0/imm32
13505     89/<- %edx 4/r32/esp
13506     (tailor-exit-descriptor %edx 0x10)
13507     #
13508     (write _test-input-stream "fn foo {\n")
13509     (write _test-input-stream "  var a/ebx: (addr array handle boolean) <- copy 0\n")
13510     (write _test-input-stream "  var o/edi: (addr handle int) <- length a\n")
13511     (write _test-input-stream "}\n")
13512     # convert
13513     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13514     # registers except esp clobbered at this point
13515     # restore ed
13516     89/<- %edx 4/r32/esp
13517     (flush _test-output-buffered-file)
13518     (flush _test-error-buffered-file)
13519 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13525     # check output
13526     (check-stream-equal _test-output-stream  ""  "F - test-length-with-wrong-output-compound-type: output should be empty")
13527     (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")
13528     # check that stop(1) was called
13529     (check-ints-equal *(edx+4) 2 "F - test-length-with-wrong-output-compound-type: exit status")
13530     # don't restore from ebp
13531     81 0/subop/add %esp 8/imm32
13532     # . epilogue
13533     5d/pop-to-ebp
13534     c3/return
13535 
13536 test-length-with-no-inouts:
13537     # . prologue
13538     55/push-ebp
13539     89/<- %ebp 4/r32/esp
13540     # setup
13541     (clear-stream _test-input-stream)
13542     (clear-stream $_test-input-buffered-file->buffer)
13543     (clear-stream _test-output-stream)
13544     (clear-stream $_test-output-buffered-file->buffer)
13545     (clear-stream _test-error-stream)
13546     (clear-stream $_test-error-buffered-file->buffer)
13547     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13548     68/push 0/imm32
13549     68/push 0/imm32
13550     89/<- %edx 4/r32/esp
13551     (tailor-exit-descriptor %edx 0x10)
13552     #
13553     (write _test-input-stream "fn foo {\n")
13554     (write _test-input-stream "  var c/ecx: int <- length\n")
13555     (write _test-input-stream "}\n")
13556     # convert
13557     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13558     # registers except esp clobbered at this point
13559     # restore ed
13560     89/<- %edx 4/r32/esp
13561     (flush _test-output-buffered-file)
13562     (flush _test-error-buffered-file)
13563 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13569     # check output
13570     (check-stream-equal _test-output-stream  ""  "F - test-length-with-no-inouts: output should be empty")
13571     (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")
13572     # check that stop(1) was called
13573     (check-ints-equal *(edx+4) 2 "F - test-length-with-no-inouts: exit status")
13574     # don't restore from ebp
13575     81 0/subop/add %esp 8/imm32
13576     # . epilogue
13577     5d/pop-to-ebp
13578     c3/return
13579 
13580 test-length-with-too-many-inouts:
13581     # . prologue
13582     55/push-ebp
13583     89/<- %ebp 4/r32/esp
13584     # setup
13585     (clear-stream _test-input-stream)
13586     (clear-stream $_test-input-buffered-file->buffer)
13587     (clear-stream _test-output-stream)
13588     (clear-stream $_test-output-buffered-file->buffer)
13589     (clear-stream _test-error-stream)
13590     (clear-stream $_test-error-buffered-file->buffer)
13591     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13592     68/push 0/imm32
13593     68/push 0/imm32
13594     89/<- %edx 4/r32/esp
13595     (tailor-exit-descriptor %edx 0x10)
13596     #
13597     (write _test-input-stream "fn foo {\n")
13598     (write _test-input-stream "  var a: (array int 3)\n")
13599     (write _test-input-stream "  var c/ecx: int <- length a, 0, 0\n")
13600     (write _test-input-stream "}\n")
13601     # convert
13602     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13603     # registers except esp clobbered at this point
13604     # restore ed
13605     89/<- %edx 4/r32/esp
13606     (flush _test-output-buffered-file)
13607     (flush _test-error-buffered-file)
13608 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13614     # check output
13615     (check-stream-equal _test-output-stream  ""  "F - test-length-with-too-many-inouts: output should be empty")
13616     (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")
13617     # check that stop(1) was called
13618     (check-ints-equal *(edx+4) 2 "F - test-length-with-too-many-inouts: exit status")
13619     # don't restore from ebp
13620     81 0/subop/add %esp 8/imm32
13621     # . epilogue
13622     5d/pop-to-ebp
13623     c3/return
13624 
13625 test-length-with-no-output:
13626     # . prologue
13627     55/push-ebp
13628     89/<- %ebp 4/r32/esp
13629     # setup
13630     (clear-stream _test-input-stream)
13631     (clear-stream $_test-input-buffered-file->buffer)
13632     (clear-stream _test-output-stream)
13633     (clear-stream $_test-output-buffered-file->buffer)
13634     (clear-stream _test-error-stream)
13635     (clear-stream $_test-error-buffered-file->buffer)
13636     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13637     68/push 0/imm32
13638     68/push 0/imm32
13639     89/<- %edx 4/r32/esp
13640     (tailor-exit-descriptor %edx 0x10)
13641     #
13642     (write _test-input-stream "fn foo {\n")
13643     (write _test-input-stream "  var a: (array int 3)\n")
13644     (write _test-input-stream "  length a\n")
13645     (write _test-input-stream "}\n")
13646     # convert
13647     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13648     # registers except esp clobbered at this point
13649     # restore ed
13650     89/<- %edx 4/r32/esp
13651     (flush _test-output-buffered-file)
13652     (flush _test-error-buffered-file)
13653 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13659     # check output
13660     (check-stream-equal _test-output-stream  ""  "F - test-length-with-no-output: output should be empty")
13661     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt length: must have an output"  "F - test-length-with-no-output: error message")
13662     # check that stop(1) was called
13663     (check-ints-equal *(edx+4) 2 "F - test-length-with-no-output: exit status")
13664     # don't restore from ebp
13665     81 0/subop/add %esp 8/imm32
13666     # . epilogue
13667     5d/pop-to-ebp
13668     c3/return
13669 
13670 test-length-with-too-many-outputs:
13671     # . prologue
13672     55/push-ebp
13673     89/<- %ebp 4/r32/esp
13674     # setup
13675     (clear-stream _test-input-stream)
13676     (clear-stream $_test-input-buffered-file->buffer)
13677     (clear-stream _test-output-stream)
13678     (clear-stream $_test-output-buffered-file->buffer)
13679     (clear-stream _test-error-stream)
13680     (clear-stream $_test-error-buffered-file->buffer)
13681     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13682     68/push 0/imm32
13683     68/push 0/imm32
13684     89/<- %edx 4/r32/esp
13685     (tailor-exit-descriptor %edx 0x10)
13686     #
13687     (write _test-input-stream "fn foo {\n")
13688     (write _test-input-stream "  var a: (array int 3)\n")
13689     (write _test-input-stream "  var b/eax: int <- copy 0\n")
13690     (write _test-input-stream "  var c/ecx: int <- copy 0\n")
13691     (write _test-input-stream "  b, c <- length a\n")
13692     (write _test-input-stream "}\n")
13693     # convert
13694     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13695     # registers except esp clobbered at this point
13696     # restore ed
13697     89/<- %edx 4/r32/esp
13698     (flush _test-output-buffered-file)
13699     (flush _test-error-buffered-file)
13700 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13706     # check output
13707     (check-stream-equal _test-output-stream  ""  "F - test-length-with-too-many-outputs: output should be empty")
13708     (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")
13709     # check that stop(1) was called
13710     (check-ints-equal *(edx+4) 2 "F - test-length-with-too-many-outputs: exit status")
13711     # don't restore from ebp
13712     81 0/subop/add %esp 8/imm32
13713     # . epilogue
13714     5d/pop-to-ebp
13715     c3/return
13716 
13717 test-convert-function-with-return-register-and-local:
13718     # . prologue
13719     55/push-ebp
13720     89/<- %ebp 4/r32/esp
13721     # setup
13722     (clear-stream _test-input-stream)
13723     (clear-stream $_test-input-buffered-file->buffer)
13724     (clear-stream _test-output-stream)
13725     (clear-stream $_test-output-buffered-file->buffer)
13726     #
13727     (write _test-input-stream "fn foo -> _/eax: int {\n")
13728     (write _test-input-stream "  var y/eax: int <- copy 3\n")
13729     (write _test-input-stream "  var z/ecx: int <- copy 4\n")
13730     (write _test-input-stream "  return y\n")
13731     (write _test-input-stream "}\n")
13732     # convert
13733     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
13734     (flush _test-output-buffered-file)
13735 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
13741     # check output
13742     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-register-and-local/0")
13743     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-register-and-local/1")
13744     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-register-and-local/2")
13745     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-register-and-local/3")
13746     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-register-and-local/4")
13747     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-register-and-local/5")
13748     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-with-return-register-and-local/6")
13749     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 3/imm32"  "F - test-convert-function-with-return-register-and-local/7")
13750     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-return-register-and-local/8")
13751     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 4/imm32"  "F - test-convert-function-with-return-register-and-local/9")
13752     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32" "F - test-convert-function-with-return-register-and-local/10")
13753     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-function-with-return-register-and-local/11")
13754     (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")
13755     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-register-and-local/13")
13756     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-register-and-local/14")
13757     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-register-and-local/15")
13758     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-register-and-local/16")
13759     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-register-and-local/17")
13760     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-register-and-local/18")
13761     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-register-and-local/19")
13762     # . epilogue
13763     89/<- %esp 5/r32/ebp
13764     5d/pop-to-ebp
13765     c3/return
13766 
13767 test-convert-function-with-return-register-and-local-2:
13768     # . prologue
13769     55/push-ebp
13770     89/<- %ebp 4/r32/esp
13771     # setup
13772     (clear-stream _test-input-stream)
13773     (clear-stream $_test-input-buffered-file->buffer)
13774     (clear-stream _test-output-stream)
13775     (clear-stream $_test-output-buffered-file->buffer)
13776     #
13777     (write _test-input-stream "fn foo -> _/eax: int {\n")
13778     (write _test-input-stream "  var y/eax: int <- copy 3\n")
13779     (write _test-input-stream "  var z/ecx: int <- copy 4\n")
13780     (write _test-input-stream "  return z\n")
13781     (write _test-input-stream "}\n")
13782     # convert
13783     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
13784     (flush _test-output-buffered-file)
13785 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
13791     # check output
13792     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-register-and-local-2/0")
13793     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-register-and-local-2/1")
13794     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-register-and-local-2/2")
13795     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-register-and-local-2/3")
13796     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-register-and-local-2/4")
13797     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-register-and-local-2/5")
13798     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-with-return-register-and-local-2/6")
13799     (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")
13800     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-return-register-and-local-2/8")
13801     (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")
13802     (check-next-stream-line-equal _test-output-stream "    8b/-> %ecx 0x00000000/r32" "F - test-convert-function-with-return-register-and-local-2/10")
13803     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-function-with-return-register-and-local-2/11")
13804     (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")
13805     (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")
13806     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-register-and-local-2/14")
13807     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-register-and-local-2/15")
13808     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-register-and-local-2/16")
13809     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-register-and-local-2/17")
13810     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-register-and-local-2/18")
13811     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-register-and-local-2/19")
13812     # . epilogue
13813     89/<- %esp 5/r32/ebp
13814     5d/pop-to-ebp
13815     c3/return
13816 
13817 test-convert-function-with-return-float-register-and-local:
13818     # . prologue
13819     55/push-ebp
13820     89/<- %ebp 4/r32/esp
13821     # setup
13822     (clear-stream _test-input-stream)
13823     (clear-stream $_test-input-buffered-file->buffer)
13824     (clear-stream _test-output-stream)
13825     (clear-stream $_test-output-buffered-file->buffer)
13826     #
13827     (write _test-input-stream "fn foo -> _/xmm1: float {\n")
13828     (write _test-input-stream "  var y/eax: int <- copy 3\n")
13829     (write _test-input-stream "  var g/xmm0: float <- convert y\n")
13830     (write _test-input-stream "  var h/xmm1: float <- convert y\n")
13831     (write _test-input-stream "  return g\n")
13832     (write _test-input-stream "}\n")
13833     # convert
13834     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
13835     (flush _test-output-buffered-file)
13836 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
13842     # check output
13843     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-float-register-and-local/0")
13844     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-float-register-and-local/1")
13845     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-float-register-and-local/2")
13846     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-float-register-and-local/3")
13847     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-float-register-and-local/4")
13848     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-float-register-and-local/5")
13849     (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
13850     (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")
13851     (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
13852     (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")
13853     (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")
13854     (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
13855     (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")
13856     (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")
13857     (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
13858     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-floating-point-dereferenced/15")  # reclaim h
13859     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 0/x32"  "F - test-convert-floating-point-dereferenced/16")  # reclaim g
13860     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-floating-point-dereferenced/17")
13861     (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
13862     (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")
13863     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-float-register-and-local/20")
13864     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-float-register-and-local/21")
13865     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-float-register-and-local/22")
13866     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-float-register-and-local/23")
13867     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-float-register-and-local/24")
13868     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-float-register-and-local/25")
13869     # . epilogue
13870     89/<- %esp 5/r32/ebp
13871     5d/pop-to-ebp
13872     c3/return
13873 
13874 test-convert-function-with-return-and-local-vars:
13875     # . prologue
13876     55/push-ebp
13877     89/<- %ebp 4/r32/esp
13878     # setup
13879     (clear-stream _test-input-stream)
13880     (clear-stream $_test-input-buffered-file->buffer)
13881     (clear-stream _test-output-stream)
13882     (clear-stream $_test-output-buffered-file->buffer)
13883     #
13884     (write _test-input-stream "fn foo -> _/eax: int {\n")
13885     (write _test-input-stream "  {\n")
13886     (write _test-input-stream "    var x: int\n")
13887     (write _test-input-stream "    {\n")
13888     (write _test-input-stream "      var y: int\n")
13889     (write _test-input-stream "      return y\n")
13890     (write _test-input-stream "      increment x\n")
13891     (write _test-input-stream "    }\n")
13892     (write _test-input-stream "  }\n")
13893     (write _test-input-stream "  return 0\n")
13894     (write _test-input-stream "}\n")
13895     # convert
13896     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
13897     (flush _test-output-buffered-file)
13898 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
13904     # check output
13905     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-and-local-vars/0")
13906     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-and-local-vars/1")
13907     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-and-local-vars/2")
13908     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-and-local-vars/3")
13909     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-and-local-vars/4")
13910     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-and-local-vars/5")
13911     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-return-and-local-vars/6")
13912     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-return-and-local-vars/7")
13913     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-return-and-local-vars/8")  # var x
13914     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-return-and-local-vars/9")
13915     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-return-and-local-vars/10")
13916     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-return-and-local-vars/11")  # var y
13917     (check-next-stream-line-equal _test-output-stream "        8b/-> *(ebp+0xfffffff8) 0x00000000/r32" "F - test-convert-function-with-return-and-local-vars/12")
13918     (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")
13919     (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")
13920     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-and-local-vars/15")
13921     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-return-and-local-vars/16")
13922     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-return-and-local-vars/17")
13923     (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")
13924     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-return-and-local-vars/19")
13925     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-return-and-local-vars/20")
13926     (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")
13927     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-and-local-vars/21")
13928     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-and-local-vars/21")
13929     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-and-local-vars/22")
13930     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-and-local-vars/23")
13931     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-and-local-vars/24")
13932     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-and-local-vars/25")
13933     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-and-local-vars/26")
13934     # . epilogue
13935     89/<- %esp 5/r32/ebp
13936     5d/pop-to-ebp
13937     c3/return
13938 
13939 test-copy-object-with-no-inout:
13940     # . prologue
13941     55/push-ebp
13942     89/<- %ebp 4/r32/esp
13943     # setup
13944     (clear-stream _test-input-stream)
13945     (clear-stream $_test-input-buffered-file->buffer)
13946     (clear-stream _test-output-stream)
13947     (clear-stream $_test-output-buffered-file->buffer)
13948     (clear-stream _test-error-stream)
13949     (clear-stream $_test-error-buffered-file->buffer)
13950     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13951     68/push 0/imm32
13952     68/push 0/imm32
13953     89/<- %edx 4/r32/esp
13954     (tailor-exit-descriptor %edx 0x10)
13955     #
13956     (write _test-input-stream "fn foo {\n")
13957     (write _test-input-stream "  copy-object\n")
13958     (write _test-input-stream "}\n")
13959     # convert
13960     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13961     # registers except esp clobbered at this point
13962     # restore ed
13963     89/<- %edx 4/r32/esp
13964     (flush _test-output-buffered-file)
13965     (flush _test-error-buffered-file)
13966 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13972     # check output
13973     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-with-no-inout: output should be empty")
13974     (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")
13975     # check that stop(1) was called
13976     (check-ints-equal *(edx+4) 2 "F - test-copy-object-with-no-inout: exit status")
13977     # don't restore from ebp
13978     81 0/subop/add %esp 8/imm32
13979     # . epilogue
13980     5d/pop-to-ebp
13981     c3/return
13982 
13983 test-copy-object-with-no-source:
13984     # . prologue
13985     55/push-ebp
13986     89/<- %ebp 4/r32/esp
13987     # setup
13988     (clear-stream _test-input-stream)
13989     (clear-stream $_test-input-buffered-file->buffer)
13990     (clear-stream _test-output-stream)
13991     (clear-stream $_test-output-buffered-file->buffer)
13992     (clear-stream _test-error-stream)
13993     (clear-stream $_test-error-buffered-file->buffer)
13994     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13995     68/push 0/imm32
13996     68/push 0/imm32
13997     89/<- %edx 4/r32/esp
13998     (tailor-exit-descriptor %edx 0x10)
13999     #
14000     (write _test-input-stream "fn foo {\n")
14001     (write _test-input-stream "  var x: (addr int)\n")
14002     (write _test-input-stream "  copy-object x\n")
14003     (write _test-input-stream "}\n")
14004     # convert
14005     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14006     # registers except esp clobbered at this point
14007     # restore ed
14008     89/<- %edx 4/r32/esp
14009     (flush _test-output-buffered-file)
14010     (flush _test-error-buffered-file)
14011 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14017     # check output
14018     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-with-no-source: output should be empty")
14019     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-object' must have two inouts"  "F - test-copy-object-with-no-source: error message")
14020     # check that stop(1) was called
14021     (check-ints-equal *(edx+4) 2 "F - test-copy-object-with-no-source: exit status")
14022     # don't restore from ebp
14023     81 0/subop/add %esp 8/imm32
14024     # . epilogue
14025     5d/pop-to-ebp
14026     c3/return
14027 
14028 test-copy-object-with-too-many-inouts:
14029     # . prologue
14030     55/push-ebp
14031     89/<- %ebp 4/r32/esp
14032     # setup
14033     (clear-stream _test-input-stream)
14034     (clear-stream $_test-input-buffered-file->buffer)
14035     (clear-stream _test-output-stream)
14036     (clear-stream $_test-output-buffered-file->buffer)
14037     (clear-stream _test-error-stream)
14038     (clear-stream $_test-error-buffered-file->buffer)
14039     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14040     68/push 0/imm32
14041     68/push 0/imm32
14042     89/<- %edx 4/r32/esp
14043     (tailor-exit-descriptor %edx 0x10)
14044     #
14045     (write _test-input-stream "fn foo {\n")
14046     (write _test-input-stream "  var x: (addr boolean)\n")
14047     (write _test-input-stream "  copy-object x, x, x\n")
14048     (write _test-input-stream "}\n")
14049     # convert
14050     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14051     # registers except esp clobbered at this point
14052     # restore ed
14053     89/<- %edx 4/r32/esp
14054     (flush _test-output-buffered-file)
14055     (flush _test-error-buffered-file)
14056 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14062     # check output
14063     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-with-too-many-inouts: output should be empty")
14064     (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")
14065     # check that stop(1) was called
14066     (check-ints-equal *(edx+4) 2 "F - test-copy-object-with-too-many-inouts: exit status")
14067     # don't restore from ebp
14068     81 0/subop/add %esp 8/imm32
14069     # . epilogue
14070     5d/pop-to-ebp
14071     c3/return
14072 
14073 test-copy-object-with-output:
14074     # . prologue
14075     55/push-ebp
14076     89/<- %ebp 4/r32/esp
14077     # setup
14078     (clear-stream _test-input-stream)
14079     (clear-stream $_test-input-buffered-file->buffer)
14080     (clear-stream _test-output-stream)
14081     (clear-stream $_test-output-buffered-file->buffer)
14082     (clear-stream _test-error-stream)
14083     (clear-stream $_test-error-buffered-file->buffer)
14084     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14085     68/push 0/imm32
14086     68/push 0/imm32
14087     89/<- %edx 4/r32/esp
14088     (tailor-exit-descriptor %edx 0x10)
14089     #
14090     (write _test-input-stream "fn foo {\n")
14091     (write _test-input-stream "  var x/eax: (addr boolean) <- copy 0\n")
14092     (write _test-input-stream "  var y/ecx: (addr boolean) <- copy 0\n")
14093     (write _test-input-stream "  x <- copy-object x, y\n")
14094     (write _test-input-stream "}\n")
14095     # convert
14096     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14097     # registers except esp clobbered at this point
14098     # restore ed
14099     89/<- %edx 4/r32/esp
14100     (flush _test-output-buffered-file)
14101     (flush _test-error-buffered-file)
14102 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14108     # check output
14109     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-with-output: output should be empty")
14110     (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")
14111     # check that stop(1) was called
14112     (check-ints-equal *(edx+4) 2 "F - test-copy-object-with-output: exit status")
14113     # don't restore from ebp
14114     81 0/subop/add %esp 8/imm32
14115     # . epilogue
14116     5d/pop-to-ebp
14117     c3/return
14118 
14119 test-copy-object-deref-address:
14120     # . prologue
14121     55/push-ebp
14122     89/<- %ebp 4/r32/esp
14123     # setup
14124     (clear-stream _test-input-stream)
14125     (clear-stream $_test-input-buffered-file->buffer)
14126     (clear-stream _test-output-stream)
14127     (clear-stream $_test-output-buffered-file->buffer)
14128     #
14129     (write _test-input-stream "fn foo {\n")
14130     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
14131     (write _test-input-stream "  var y/ecx: (addr addr int) <- copy 0\n")
14132     (write _test-input-stream "  copy-object *y, x\n")
14133     (write _test-input-stream "}\n")
14134     # convert
14135     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
14136     (flush _test-output-buffered-file)
14137     # no errors
14138     # . epilogue
14139     5d/pop-to-ebp
14140     c3/return
14141 
14142 test-copy-object-non-addr:
14143     # . prologue
14144     55/push-ebp
14145     89/<- %ebp 4/r32/esp
14146     # setup
14147     (clear-stream _test-input-stream)
14148     (clear-stream $_test-input-buffered-file->buffer)
14149     (clear-stream _test-output-stream)
14150     (clear-stream $_test-output-buffered-file->buffer)
14151     (clear-stream _test-error-stream)
14152     (clear-stream $_test-error-buffered-file->buffer)
14153     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14154     68/push 0/imm32
14155     68/push 0/imm32
14156     89/<- %edx 4/r32/esp
14157     (tailor-exit-descriptor %edx 0x10)
14158     #
14159     (write _test-input-stream "fn foo {\n")
14160     (write _test-input-stream "  var x: int\n")
14161     (write _test-input-stream "  var y: int\n")
14162     (write _test-input-stream "  copy-object y, x\n")
14163     (write _test-input-stream "}\n")
14164     # convert
14165     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14166     # registers except esp clobbered at this point
14167     # restore ed
14168     89/<- %edx 4/r32/esp
14169     (flush _test-output-buffered-file)
14170     (flush _test-error-buffered-file)
14171 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14177     # check output
14178     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-non-addr: output should be empty")
14179     (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")
14180     # check that stop(1) was called
14181     (check-ints-equal *(edx+4) 2 "F - test-copy-object-non-addr: exit status")
14182     # don't restore from ebp
14183     81 0/subop/add %esp 8/imm32
14184     # . epilogue
14185     5d/pop-to-ebp
14186     c3/return
14187 
14188 test-copy-object-non-equal:
14189     # . prologue
14190     55/push-ebp
14191     89/<- %ebp 4/r32/esp
14192     # setup
14193     (clear-stream _test-input-stream)
14194     (clear-stream $_test-input-buffered-file->buffer)
14195     (clear-stream _test-output-stream)
14196     (clear-stream $_test-output-buffered-file->buffer)
14197     (clear-stream _test-error-stream)
14198     (clear-stream $_test-error-buffered-file->buffer)
14199     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14200     68/push 0/imm32
14201     68/push 0/imm32
14202     89/<- %edx 4/r32/esp
14203     (tailor-exit-descriptor %edx 0x10)
14204     #
14205     (write _test-input-stream "fn foo {\n")
14206     (write _test-input-stream "  var x: (addr int)\n")
14207     (write _test-input-stream "  var y: (addr boolean)\n")
14208     (write _test-input-stream "  copy-object y, x\n")
14209     (write _test-input-stream "}\n")
14210     # convert
14211     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14212     # registers except esp clobbered at this point
14213     # restore ed
14214     89/<- %edx 4/r32/esp
14215     (flush _test-output-buffered-file)
14216     (flush _test-error-buffered-file)
14217 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14223     # check output
14224     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-non-equal: output should be empty")
14225     (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")
14226     # check that stop(1) was called
14227     (check-ints-equal *(edx+4) 2 "F - test-copy-object-non-equal: exit status")
14228     # don't restore from ebp
14229     81 0/subop/add %esp 8/imm32
14230     # . epilogue
14231     5d/pop-to-ebp
14232     c3/return
14233 
14234 test-allocate-with-no-inout:
14235     # . prologue
14236     55/push-ebp
14237     89/<- %ebp 4/r32/esp
14238     # setup
14239     (clear-stream _test-input-stream)
14240     (clear-stream $_test-input-buffered-file->buffer)
14241     (clear-stream _test-output-stream)
14242     (clear-stream $_test-output-buffered-file->buffer)
14243     (clear-stream _test-error-stream)
14244     (clear-stream $_test-error-buffered-file->buffer)
14245     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14246     68/push 0/imm32
14247     68/push 0/imm32
14248     89/<- %edx 4/r32/esp
14249     (tailor-exit-descriptor %edx 0x10)
14250     #
14251     (write _test-input-stream "fn foo {\n")
14252     (write _test-input-stream "  allocate\n")
14253     (write _test-input-stream "}\n")
14254     # convert
14255     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14256     # registers except esp clobbered at this point
14257     # restore ed
14258     89/<- %edx 4/r32/esp
14259     (flush _test-output-buffered-file)
14260     (flush _test-error-buffered-file)
14261 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14267     # check output
14268     (check-stream-equal _test-output-stream  ""  "F - test-allocate-with-no-inout: output should be empty")
14269     (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")
14270     # check that stop(1) was called
14271     (check-ints-equal *(edx+4) 2 "F - test-allocate-with-no-inout: exit status")
14272     # don't restore from ebp
14273     81 0/subop/add %esp 8/imm32
14274     # . epilogue
14275     5d/pop-to-ebp
14276     c3/return
14277 
14278 test-allocate-with-too-many-inouts:
14279     # . prologue
14280     55/push-ebp
14281     89/<- %ebp 4/r32/esp
14282     # setup
14283     (clear-stream _test-input-stream)
14284     (clear-stream $_test-input-buffered-file->buffer)
14285     (clear-stream _test-output-stream)
14286     (clear-stream $_test-output-buffered-file->buffer)
14287     (clear-stream _test-error-stream)
14288     (clear-stream $_test-error-buffered-file->buffer)
14289     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14290     68/push 0/imm32
14291     68/push 0/imm32
14292     89/<- %edx 4/r32/esp
14293     (tailor-exit-descriptor %edx 0x10)
14294     #
14295     (write _test-input-stream "fn foo {\n")
14296     (write _test-input-stream "  var x: (addr handle int)\n")
14297     (write _test-input-stream "  allocate x, 0\n")
14298     (write _test-input-stream "}\n")
14299     # convert
14300     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14301     # registers except esp clobbered at this point
14302     # restore ed
14303     89/<- %edx 4/r32/esp
14304     (flush _test-output-buffered-file)
14305     (flush _test-error-buffered-file)
14306 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14312     # check output
14313     (check-stream-equal _test-output-stream  ""  "F - test-allocate-with-too-many-inouts: output should be empty")
14314     (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")
14315     # check that stop(1) was called
14316     (check-ints-equal *(edx+4) 2 "F - test-allocate-with-too-many-inouts: exit status")
14317     # don't restore from ebp
14318     81 0/subop/add %esp 8/imm32
14319     # . epilogue
14320     5d/pop-to-ebp
14321     c3/return
14322 
14323 test-allocate-with-output:
14324     # . prologue
14325     55/push-ebp
14326     89/<- %ebp 4/r32/esp
14327     # setup
14328     (clear-stream _test-input-stream)
14329     (clear-stream $_test-input-buffered-file->buffer)
14330     (clear-stream _test-output-stream)
14331     (clear-stream $_test-output-buffered-file->buffer)
14332     (clear-stream _test-error-stream)
14333     (clear-stream $_test-error-buffered-file->buffer)
14334     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14335     68/push 0/imm32
14336     68/push 0/imm32
14337     89/<- %edx 4/r32/esp
14338     (tailor-exit-descriptor %edx 0x10)
14339     #
14340     (write _test-input-stream "fn foo {\n")
14341     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
14342     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
14343     (write _test-input-stream "  x <- allocate y\n")
14344     (write _test-input-stream "}\n")
14345     # convert
14346     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14347     # registers except esp clobbered at this point
14348     # restore ed
14349     89/<- %edx 4/r32/esp
14350     (flush _test-output-buffered-file)
14351     (flush _test-error-buffered-file)
14352 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14358     # check output
14359     (check-stream-equal _test-output-stream  ""  "F - test-allocate-with-output: output should be empty")
14360     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'allocate' must not have any outputs"  "F - test-allocate-with-output: error message")
14361     # check that stop(1) was called
14362     (check-ints-equal *(edx+4) 2 "F - test-allocate-with-output: exit status")
14363     # don't restore from ebp
14364     81 0/subop/add %esp 8/imm32
14365     # . epilogue
14366     5d/pop-to-ebp
14367     c3/return
14368 
14369 test-allocate-non-addr:
14370     # . prologue
14371     55/push-ebp
14372     89/<- %ebp 4/r32/esp
14373     # setup
14374     (clear-stream _test-input-stream)
14375     (clear-stream $_test-input-buffered-file->buffer)
14376     (clear-stream _test-output-stream)
14377     (clear-stream $_test-output-buffered-file->buffer)
14378     (clear-stream _test-error-stream)
14379     (clear-stream $_test-error-buffered-file->buffer)
14380     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14381     68/push 0/imm32
14382     68/push 0/imm32
14383     89/<- %edx 4/r32/esp
14384     (tailor-exit-descriptor %edx 0x10)
14385     #
14386     (write _test-input-stream "fn foo {\n")
14387     (write _test-input-stream "  var y: (handle int)\n")
14388     (write _test-input-stream "  allocate y\n")
14389     (write _test-input-stream "}\n")
14390     # convert
14391     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14392     # registers except esp clobbered at this point
14393     # restore ed
14394     89/<- %edx 4/r32/esp
14395     (flush _test-output-buffered-file)
14396     (flush _test-error-buffered-file)
14397 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14403     # check output
14404     (check-stream-equal _test-output-stream  ""  "F - test-allocate-non-addr: output must be empty")
14405     (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")
14406     # check that stop(1) was called
14407     (check-ints-equal *(edx+4) 2 "F - test-allocate-non-addr: exit status")
14408     # don't restore from ebp
14409     81 0/subop/add %esp 8/imm32
14410     # . epilogue
14411     5d/pop-to-ebp
14412     c3/return
14413 
14414 test-allocate-non-addr-handle:
14415     # . prologue
14416     55/push-ebp
14417     89/<- %ebp 4/r32/esp
14418     # setup
14419     (clear-stream _test-input-stream)
14420     (clear-stream $_test-input-buffered-file->buffer)
14421     (clear-stream _test-output-stream)
14422     (clear-stream $_test-output-buffered-file->buffer)
14423     (clear-stream _test-error-stream)
14424     (clear-stream $_test-error-buffered-file->buffer)
14425     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14426     68/push 0/imm32
14427     68/push 0/imm32
14428     89/<- %edx 4/r32/esp
14429     (tailor-exit-descriptor %edx 0x10)
14430     #
14431     (write _test-input-stream "fn foo {\n")
14432     (write _test-input-stream "  var y/ecx: (addr int) <- copy 0\n")
14433     (write _test-input-stream "  allocate y\n")
14434     (write _test-input-stream "}\n")
14435     # convert
14436     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14437     # registers except esp clobbered at this point
14438     # restore ed
14439     89/<- %edx 4/r32/esp
14440     (flush _test-output-buffered-file)
14441     (flush _test-error-buffered-file)
14442 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14448     # check output
14449     (check-stream-equal _test-output-stream  ""  "F - test-allocate-non-addr-handle: output should be empty")
14450     (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")
14451     # check that stop(1) was called
14452     (check-ints-equal *(edx+4) 2 "F - test-allocate-non-addr-handle: exit status")
14453     # don't restore from ebp
14454     81 0/subop/add %esp 8/imm32
14455     # . epilogue
14456     5d/pop-to-ebp
14457     c3/return
14458 
14459 test-allocate-deref-address:
14460     # . prologue
14461     55/push-ebp
14462     89/<- %ebp 4/r32/esp
14463     # setup
14464     (clear-stream _test-input-stream)
14465     (clear-stream $_test-input-buffered-file->buffer)
14466     (clear-stream _test-output-stream)
14467     (clear-stream $_test-output-buffered-file->buffer)
14468     #
14469     (write _test-input-stream "fn foo {\n")
14470     (write _test-input-stream "  var y/ecx: (addr addr handle int) <- copy 0\n")
14471     (write _test-input-stream "  allocate *y\n")
14472     (write _test-input-stream "}\n")
14473     # convert
14474     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
14475     (flush _test-output-buffered-file)
14476     # no errors
14477     # . epilogue
14478     5d/pop-to-ebp
14479     c3/return
14480 
14481 test-populate-with-no-inout:
14482     # . prologue
14483     55/push-ebp
14484     89/<- %ebp 4/r32/esp
14485     # setup
14486     (clear-stream _test-input-stream)
14487     (clear-stream $_test-input-buffered-file->buffer)
14488     (clear-stream _test-output-stream)
14489     (clear-stream $_test-output-buffered-file->buffer)
14490     (clear-stream _test-error-stream)
14491     (clear-stream $_test-error-buffered-file->buffer)
14492     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14493     68/push 0/imm32
14494     68/push 0/imm32
14495     89/<- %edx 4/r32/esp
14496     (tailor-exit-descriptor %edx 0x10)
14497     #
14498     (write _test-input-stream "fn foo {\n")
14499     (write _test-input-stream "  populate\n")
14500     (write _test-input-stream "}\n")
14501     # convert
14502     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14503     # registers except esp clobbered at this point
14504     # restore ed
14505     89/<- %edx 4/r32/esp
14506     (flush _test-output-buffered-file)
14507     (flush _test-error-buffered-file)
14508 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14514     # check output
14515     (check-stream-equal _test-output-stream  ""  "F - test-populate-with-no-inout: output should be empty")
14516     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'populate' must have two inouts"  "F - test-populate-with-no-inout: error message")
14517     # check that stop(1) was called
14518     (check-ints-equal *(edx+4) 2 "F - test-populate-with-no-inout: exit status")
14519     # don't restore from ebp
14520     81 0/subop/add %esp 8/imm32
14521     # . epilogue
14522     5d/pop-to-ebp
14523     c3/return
14524 
14525 test-populate-with-too-many-inouts:
14526     # . prologue
14527     55/push-ebp
14528     89/<- %ebp 4/r32/esp
14529     # setup
14530     (clear-stream _test-input-stream)
14531     (clear-stream $_test-input-buffered-file->buffer)
14532     (clear-stream _test-output-stream)
14533     (clear-stream $_test-output-buffered-file->buffer)
14534     (clear-stream _test-error-stream)
14535     (clear-stream $_test-error-buffered-file->buffer)
14536     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14537     68/push 0/imm32
14538     68/push 0/imm32
14539     89/<- %edx 4/r32/esp
14540     (tailor-exit-descriptor %edx 0x10)
14541     #
14542     (write _test-input-stream "fn foo {\n")
14543     (write _test-input-stream "  var x: (addr handle int)\n")
14544     (write _test-input-stream "  populate x, 3, 0\n")
14545     (write _test-input-stream "}\n")
14546     # convert
14547     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14548     # registers except esp clobbered at this point
14549     # restore ed
14550     89/<- %edx 4/r32/esp
14551     (flush _test-output-buffered-file)
14552     (flush _test-error-buffered-file)
14553 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14559     # check output
14560     (check-stream-equal _test-output-stream  ""  "F - test-populate-with-too-many-inouts: output should be empty")
14561     (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")
14562     # check that stop(1) was called
14563     (check-ints-equal *(edx+4) 2 "F - test-populate-with-too-many-inouts: exit status")
14564     # don't restore from ebp
14565     81 0/subop/add %esp 8/imm32
14566     # . epilogue
14567     5d/pop-to-ebp
14568     c3/return
14569 
14570 test-populate-with-output:
14571     # . prologue
14572     55/push-ebp
14573     89/<- %ebp 4/r32/esp
14574     # setup
14575     (clear-stream _test-input-stream)
14576     (clear-stream $_test-input-buffered-file->buffer)
14577     (clear-stream _test-output-stream)
14578     (clear-stream $_test-output-buffered-file->buffer)
14579     (clear-stream _test-error-stream)
14580     (clear-stream $_test-error-buffered-file->buffer)
14581     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14582     68/push 0/imm32
14583     68/push 0/imm32
14584     89/<- %edx 4/r32/esp
14585     (tailor-exit-descriptor %edx 0x10)
14586     #
14587     (write _test-input-stream "fn foo {\n")
14588     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
14589     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
14590     (write _test-input-stream "  x <- populate y\n")
14591     (write _test-input-stream "}\n")
14592     # convert
14593     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14594     # registers except esp clobbered at this point
14595     # restore ed
14596     89/<- %edx 4/r32/esp
14597     (flush _test-output-buffered-file)
14598     (flush _test-error-buffered-file)
14599 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14605     # check output
14606     (check-stream-equal _test-output-stream  ""  "F - test-populate-with-output: output should be empty")
14607     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'populate' must not have any outputs"  "F - test-populate-with-output: error message")
14608     # check that stop(1) was called
14609     (check-ints-equal *(edx+4) 2 "F - test-populate-with-output: exit status")
14610     # don't restore from ebp
14611     81 0/subop/add %esp 8/imm32
14612     # . epilogue
14613     5d/pop-to-ebp
14614     c3/return
14615 
14616 test-populate-non-addr:
14617     # . prologue
14618     55/push-ebp
14619     89/<- %ebp 4/r32/esp
14620     # setup
14621     (clear-stream _test-input-stream)
14622     (clear-stream $_test-input-buffered-file->buffer)
14623     (clear-stream _test-output-stream)
14624     (clear-stream $_test-output-buffered-file->buffer)
14625     (clear-stream _test-error-stream)
14626     (clear-stream $_test-error-buffered-file->buffer)
14627     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14628     68/push 0/imm32
14629     68/push 0/imm32
14630     89/<- %edx 4/r32/esp
14631     (tailor-exit-descriptor %edx 0x10)
14632     #
14633     (write _test-input-stream "fn foo {\n")
14634     (write _test-input-stream "  var y: (handle int)\n")
14635     (write _test-input-stream "  populate y, 3\n")
14636     (write _test-input-stream "}\n")
14637     # convert
14638     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14639     # registers except esp clobbered at this point
14640     # restore ed
14641     89/<- %edx 4/r32/esp
14642     (flush _test-output-buffered-file)
14643     (flush _test-error-buffered-file)
14644 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14650     # check output
14651     (check-stream-equal _test-output-stream  ""  "F - test-populate-non-addr: output must be empty")
14652     (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")
14653     # check that stop(1) was called
14654     (check-ints-equal *(edx+4) 2 "F - test-populate-non-addr: exit status")
14655     # don't restore from ebp
14656     81 0/subop/add %esp 8/imm32
14657     # . epilogue
14658     5d/pop-to-ebp
14659     c3/return
14660 
14661 test-populate-non-addr-handle:
14662     # . prologue
14663     55/push-ebp
14664     89/<- %ebp 4/r32/esp
14665     # setup
14666     (clear-stream _test-input-stream)
14667     (clear-stream $_test-input-buffered-file->buffer)
14668     (clear-stream _test-output-stream)
14669     (clear-stream $_test-output-buffered-file->buffer)
14670     (clear-stream _test-error-stream)
14671     (clear-stream $_test-error-buffered-file->buffer)
14672     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14673     68/push 0/imm32
14674     68/push 0/imm32
14675     89/<- %edx 4/r32/esp
14676     (tailor-exit-descriptor %edx 0x10)
14677     #
14678     (write _test-input-stream "fn foo {\n")
14679     (write _test-input-stream "  var y/ecx: (addr int) <- copy 0\n")
14680     (write _test-input-stream "  populate y, 3\n")
14681     (write _test-input-stream "}\n")
14682     # convert
14683     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14684     # registers except esp clobbered at this point
14685     # restore ed
14686     89/<- %edx 4/r32/esp
14687     (flush _test-output-buffered-file)
14688     (flush _test-error-buffered-file)
14689 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14695     # check output
14696     (check-stream-equal _test-output-stream  ""  "F - test-populate-non-addr-handle: output should be empty")
14697     (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")
14698     # check that stop(1) was called
14699     (check-ints-equal *(edx+4) 2 "F - test-populate-non-addr-handle: exit status")
14700     # don't restore from ebp
14701     81 0/subop/add %esp 8/imm32
14702     # . epilogue
14703     5d/pop-to-ebp
14704     c3/return
14705 
14706 test-populate-non-addr-handle-array:
14707     # . prologue
14708     55/push-ebp
14709     89/<- %ebp 4/r32/esp
14710     # setup
14711     (clear-stream _test-input-stream)
14712     (clear-stream $_test-input-buffered-file->buffer)
14713     (clear-stream _test-output-stream)
14714     (clear-stream $_test-output-buffered-file->buffer)
14715     (clear-stream _test-error-stream)
14716     (clear-stream $_test-error-buffered-file->buffer)
14717     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14718     68/push 0/imm32
14719     68/push 0/imm32
14720     89/<- %edx 4/r32/esp
14721     (tailor-exit-descriptor %edx 0x10)
14722     #
14723     (write _test-input-stream "fn foo {\n")
14724     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
14725     (write _test-input-stream "  populate y, 3\n")
14726     (write _test-input-stream "}\n")
14727     # convert
14728     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14729     # registers except esp clobbered at this point
14730     # restore ed
14731     89/<- %edx 4/r32/esp
14732     (flush _test-output-buffered-file)
14733     (flush _test-error-buffered-file)
14734 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14740     # check output
14741     (check-stream-equal _test-output-stream  ""  "F - test-populate-non-addr-handle-array: output should be empty")
14742     (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")
14743     # check that stop(1) was called
14744     (check-ints-equal *(edx+4) 2 "F - test-populate-non-addr-handle-array: exit status")
14745     # don't restore from ebp
14746     81 0/subop/add %esp 8/imm32
14747     # . epilogue
14748     5d/pop-to-ebp
14749     c3/return
14750 
14751 test-populate-deref-address:
14752     # . prologue
14753     55/push-ebp
14754     89/<- %ebp 4/r32/esp
14755     # setup
14756     (clear-stream _test-input-stream)
14757     (clear-stream $_test-input-buffered-file->buffer)
14758     (clear-stream _test-output-stream)
14759     (clear-stream $_test-output-buffered-file->buffer)
14760     #
14761     (write _test-input-stream "fn foo {\n")
14762     (write _test-input-stream "  var y/ecx: (addr addr handle array int) <- copy 0\n")
14763     (write _test-input-stream "  populate *y, 3\n")
14764     (write _test-input-stream "}\n")
14765     # convert
14766     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
14767     (flush _test-output-buffered-file)
14768     # no errors
14769     # . epilogue
14770     5d/pop-to-ebp
14771     c3/return
14772 
14773 test-populate-stream-with-no-inout:
14774     # . prologue
14775     55/push-ebp
14776     89/<- %ebp 4/r32/esp
14777     # setup
14778     (clear-stream _test-input-stream)
14779     (clear-stream $_test-input-buffered-file->buffer)
14780     (clear-stream _test-output-stream)
14781     (clear-stream $_test-output-buffered-file->buffer)
14782     (clear-stream _test-error-stream)
14783     (clear-stream $_test-error-buffered-file->buffer)
14784     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14785     68/push 0/imm32
14786     68/push 0/imm32
14787     89/<- %edx 4/r32/esp
14788     (tailor-exit-descriptor %edx 0x10)
14789     #
14790     (write _test-input-stream "fn foo {\n")
14791     (write _test-input-stream "  populate-stream\n")
14792     (write _test-input-stream "}\n")
14793     # convert
14794     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14795     # registers except esp clobbered at this point
14796     # restore ed
14797     89/<- %edx 4/r32/esp
14798     (flush _test-output-buffered-file)
14799     (flush _test-error-buffered-file)
14800 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14806     # check output
14807     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-with-no-inout: output should be empty")
14808     (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")
14809     # check that stop(1) was called
14810     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-with-no-inout: exit status")
14811     # don't restore from ebp
14812     81 0/subop/add %esp 8/imm32
14813     # . epilogue
14814     5d/pop-to-ebp
14815     c3/return
14816 
14817 test-populate-stream-with-too-many-inouts:
14818     # . prologue
14819     55/push-ebp
14820     89/<- %ebp 4/r32/esp
14821     # setup
14822     (clear-stream _test-input-stream)
14823     (clear-stream $_test-input-buffered-file->buffer)
14824     (clear-stream _test-output-stream)
14825     (clear-stream $_test-output-buffered-file->buffer)
14826     (clear-stream _test-error-stream)
14827     (clear-stream $_test-error-buffered-file->buffer)
14828     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14829     68/push 0/imm32
14830     68/push 0/imm32
14831     89/<- %edx 4/r32/esp
14832     (tailor-exit-descriptor %edx 0x10)
14833     #
14834     (write _test-input-stream "fn foo {\n")
14835     (write _test-input-stream "  var x: (addr handle int)\n")
14836     (write _test-input-stream "  populate-stream x, 3, 0\n")
14837     (write _test-input-stream "}\n")
14838     # convert
14839     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14840     # registers except esp clobbered at this point
14841     # restore ed
14842     89/<- %edx 4/r32/esp
14843     (flush _test-output-buffered-file)
14844     (flush _test-error-buffered-file)
14845 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14851     # check output
14852     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-with-too-many-inouts: output should be empty")
14853     (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")
14854     # check that stop(1) was called
14855     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-with-too-many-inouts: exit status")
14856     # don't restore from ebp
14857     81 0/subop/add %esp 8/imm32
14858     # . epilogue
14859     5d/pop-to-ebp
14860     c3/return
14861 
14862 test-populate-stream-with-output:
14863     # . prologue
14864     55/push-ebp
14865     89/<- %ebp 4/r32/esp
14866     # setup
14867     (clear-stream _test-input-stream)
14868     (clear-stream $_test-input-buffered-file->buffer)
14869     (clear-stream _test-output-stream)
14870     (clear-stream $_test-output-buffered-file->buffer)
14871     (clear-stream _test-error-stream)
14872     (clear-stream $_test-error-buffered-file->buffer)
14873     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14874     68/push 0/imm32
14875     68/push 0/imm32
14876     89/<- %edx 4/r32/esp
14877     (tailor-exit-descriptor %edx 0x10)
14878     #
14879     (write _test-input-stream "fn foo {\n")
14880     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
14881     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
14882     (write _test-input-stream "  x <- populate-stream y\n")
14883     (write _test-input-stream "}\n")
14884     # convert
14885     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14886     # registers except esp clobbered at this point
14887     # restore ed
14888     89/<- %edx 4/r32/esp
14889     (flush _test-output-buffered-file)
14890     (flush _test-error-buffered-file)
14891 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14897     # check output
14898     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-with-output: output should be empty")
14899     (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")
14900     # check that stop(1) was called
14901     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-with-output: exit status")
14902     # don't restore from ebp
14903     81 0/subop/add %esp 8/imm32
14904     # . epilogue
14905     5d/pop-to-ebp
14906     c3/return
14907 
14908 test-populate-stream-non-addr:
14909     # . prologue
14910     55/push-ebp
14911     89/<- %ebp 4/r32/esp
14912     # setup
14913     (clear-stream _test-input-stream)
14914     (clear-stream $_test-input-buffered-file->buffer)
14915     (clear-stream _test-output-stream)
14916     (clear-stream $_test-output-buffered-file->buffer)
14917     (clear-stream _test-error-stream)
14918     (clear-stream $_test-error-buffered-file->buffer)
14919     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14920     68/push 0/imm32
14921     68/push 0/imm32
14922     89/<- %edx 4/r32/esp
14923     (tailor-exit-descriptor %edx 0x10)
14924     #
14925     (write _test-input-stream "fn foo {\n")
14926     (write _test-input-stream "  var y: (handle int)\n")
14927     (write _test-input-stream "  populate-stream y, 3\n")
14928     (write _test-input-stream "}\n")
14929     # convert
14930     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14931     # registers except esp clobbered at this point
14932     # restore ed
14933     89/<- %edx 4/r32/esp
14934     (flush _test-output-buffered-file)
14935     (flush _test-error-buffered-file)
14936 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14942     # check output
14943     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-non-addr: output must be empty")
14944     (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")
14945     # check that stop(1) was called
14946     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-non-addr: exit status")
14947     # don't restore from ebp
14948     81 0/subop/add %esp 8/imm32
14949     # . epilogue
14950     5d/pop-to-ebp
14951     c3/return
14952 
14953 test-populate-stream-non-addr-handle:
14954     # . prologue
14955     55/push-ebp
14956     89/<- %ebp 4/r32/esp
14957     # setup
14958     (clear-stream _test-input-stream)
14959     (clear-stream $_test-input-buffered-file->buffer)
14960     (clear-stream _test-output-stream)
14961     (clear-stream $_test-output-buffered-file->buffer)
14962     (clear-stream _test-error-stream)
14963     (clear-stream $_test-error-buffered-file->buffer)
14964     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14965     68/push 0/imm32
14966     68/push 0/imm32
14967     89/<- %edx 4/r32/esp
14968     (tailor-exit-descriptor %edx 0x10)
14969     #
14970     (write _test-input-stream "fn foo {\n")
14971     (write _test-input-stream "  var y/ecx: (addr int) <- copy 0\n")
14972     (write _test-input-stream "  populate-stream y, 3\n")
14973     (write _test-input-stream "}\n")
14974     # convert
14975     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14976     # registers except esp clobbered at this point
14977     # restore ed
14978     89/<- %edx 4/r32/esp
14979     (flush _test-output-buffered-file)
14980     (flush _test-error-buffered-file)
14981 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14987     # check output
14988     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-non-addr-handle: output should be empty")
14989     (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")
14990     # check that stop(1) was called
14991     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-non-addr-handle: exit status")
14992     # don't restore from ebp
14993     81 0/subop/add %esp 8/imm32
14994     # . epilogue
14995     5d/pop-to-ebp
14996     c3/return
14997 
14998 test-populate-stream-non-addr-handle-stream:
14999     # . prologue
15000     55/push-ebp
15001     89/<- %ebp 4/r32/esp
15002     # setup
15003     (clear-stream _test-input-stream)
15004     (clear-stream $_test-input-buffered-file->buffer)
15005     (clear-stream _test-output-stream)
15006     (clear-stream $_test-output-buffered-file->buffer)
15007     (clear-stream _test-error-stream)
15008     (clear-stream $_test-error-buffered-file->buffer)
15009     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15010     68/push 0/imm32
15011     68/push 0/imm32
15012     89/<- %edx 4/r32/esp
15013     (tailor-exit-descriptor %edx 0x10)
15014     #
15015     (write _test-input-stream "fn foo {\n")
15016     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
15017     (write _test-input-stream "  populate-stream y, 3\n")
15018     (write _test-input-stream "}\n")
15019     # convert
15020     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15021     # registers except esp clobbered at this point
15022     # restore ed
15023     89/<- %edx 4/r32/esp
15024     (flush _test-output-buffered-file)
15025     (flush _test-error-buffered-file)
15026 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15032     # check output
15033     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-non-addr-handle-stream: output should be empty")
15034     (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")
15035     # check that stop(1) was called
15036     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-non-addr-handle-stream: exit status")
15037     # don't restore from ebp
15038     81 0/subop/add %esp 8/imm32
15039     # . epilogue
15040     5d/pop-to-ebp
15041     c3/return
15042 
15043 test-populate-stream-deref-address:
15044     # . prologue
15045     55/push-ebp
15046     89/<- %ebp 4/r32/esp
15047     # setup
15048     (clear-stream _test-input-stream)
15049     (clear-stream $_test-input-buffered-file->buffer)
15050     (clear-stream _test-output-stream)
15051     (clear-stream $_test-output-buffered-file->buffer)
15052     #
15053     (write _test-input-stream "fn foo {\n")
15054     (write _test-input-stream "  var y/ecx: (addr addr handle stream int) <- copy 0\n")
15055     (write _test-input-stream "  populate-stream *y, 3\n")
15056     (write _test-input-stream "}\n")
15057     # convert
15058     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
15059     (flush _test-output-buffered-file)
15060     # no errors
15061     # . epilogue
15062     5d/pop-to-ebp
15063     c3/return
15064 
15065 test-convert-with-no-inout:
15066     # . prologue
15067     55/push-ebp
15068     89/<- %ebp 4/r32/esp
15069     # setup
15070     (clear-stream _test-input-stream)
15071     (clear-stream $_test-input-buffered-file->buffer)
15072     (clear-stream _test-output-stream)
15073     (clear-stream $_test-output-buffered-file->buffer)
15074     (clear-stream _test-error-stream)
15075     (clear-stream $_test-error-buffered-file->buffer)
15076     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15077     68/push 0/imm32
15078     68/push 0/imm32
15079     89/<- %edx 4/r32/esp
15080     (tailor-exit-descriptor %edx 0x10)
15081     #
15082     (write _test-input-stream "fn foo {\n")
15083     (write _test-input-stream "  var x/eax: int <- convert\n")
15084     (write _test-input-stream "}\n")
15085     # convert
15086     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15087     # registers except esp clobbered at this point
15088     # restore ed
15089     89/<- %edx 4/r32/esp
15090     (flush _test-output-buffered-file)
15091     (flush _test-error-buffered-file)
15092 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15098     # check output
15099     (check-stream-equal _test-output-stream  ""  "F - test-convert-with-no-inout: output should be empty")
15100     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'convert' expects an inout"  "F - test-convert-with-no-inout: error message")
15101     # check that stop(1) was called
15102     (check-ints-equal *(edx+4) 2 "F - test-convert-with-no-inout: exit status")
15103     # don't restore from ebp
15104     81 0/subop/add %esp 8/imm32
15105     # . epilogue
15106     5d/pop-to-ebp
15107     c3/return
15108 
15109 test-convert-with-multiple-inouts:
15110     # . prologue
15111     55/push-ebp
15112     89/<- %ebp 4/r32/esp
15113     # setup
15114     (clear-stream _test-input-stream)
15115     (clear-stream $_test-input-buffered-file->buffer)
15116     (clear-stream _test-output-stream)
15117     (clear-stream $_test-output-buffered-file->buffer)
15118     (clear-stream _test-error-stream)
15119     (clear-stream $_test-error-buffered-file->buffer)
15120     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15121     68/push 0/imm32
15122     68/push 0/imm32
15123     89/<- %edx 4/r32/esp
15124     (tailor-exit-descriptor %edx 0x10)
15125     #
15126     (write _test-input-stream "fn foo {\n")
15127     (write _test-input-stream "  var x/eax: int <- convert 0, 0\n")
15128     (write _test-input-stream "}\n")
15129     # convert
15130     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15131     # registers except esp clobbered at this point
15132     # restore ed
15133     89/<- %edx 4/r32/esp
15134     (flush _test-output-buffered-file)
15135     (flush _test-error-buffered-file)
15136 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15142     # check output
15143     (check-stream-equal _test-output-stream  ""  "F - test-convert-with-multiple-inouts: output should be empty")
15144     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'convert' must have just one inout"  "F - test-convert-with-multiple-inouts: error message")
15145     # check that stop(1) was called
15146     (check-ints-equal *(edx+4) 2 "F - test-convert-with-multiple-inouts: exit status")
15147     # don't restore from ebp
15148     81 0/subop/add %esp 8/imm32
15149     # . epilogue
15150     5d/pop-to-ebp
15151     c3/return
15152 
15153 test-convert-with-no-output:
15154     # . prologue
15155     55/push-ebp
15156     89/<- %ebp 4/r32/esp
15157     # setup
15158     (clear-stream _test-input-stream)
15159     (clear-stream $_test-input-buffered-file->buffer)
15160     (clear-stream _test-output-stream)
15161     (clear-stream $_test-output-buffered-file->buffer)
15162     (clear-stream _test-error-stream)
15163     (clear-stream $_test-error-buffered-file->buffer)
15164     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15165     68/push 0/imm32
15166     68/push 0/imm32
15167     89/<- %edx 4/r32/esp
15168     (tailor-exit-descriptor %edx 0x10)
15169     #
15170     (write _test-input-stream "fn foo {\n")
15171     (write _test-input-stream "  convert 0\n")
15172     (write _test-input-stream "}\n")
15173     # convert
15174     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15175     # registers except esp clobbered at this point
15176     # restore ed
15177     89/<- %edx 4/r32/esp
15178     (flush _test-output-buffered-file)
15179     (flush _test-error-buffered-file)
15180 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15186     # check output
15187     (check-stream-equal _test-output-stream  ""  "F - test-convert-with-no-output: output should be empty")
15188     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'convert' expects an output"  "F - test-convert-with-no-output: error message")
15189     # check that stop(1) was called
15190     (check-ints-equal *(edx+4) 2 "F - test-convert-with-no-output: exit status")
15191     # don't restore from ebp
15192     81 0/subop/add %esp 8/imm32
15193     # . epilogue
15194     5d/pop-to-ebp
15195     c3/return
15196 
15197 test-convert-with-multiple-outputs:
15198     # . prologue
15199     55/push-ebp
15200     89/<- %ebp 4/r32/esp
15201     # setup
15202     (clear-stream _test-input-stream)
15203     (clear-stream $_test-input-buffered-file->buffer)
15204     (clear-stream _test-output-stream)
15205     (clear-stream $_test-output-buffered-file->buffer)
15206     (clear-stream _test-error-stream)
15207     (clear-stream $_test-error-buffered-file->buffer)
15208     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15209     68/push 0/imm32
15210     68/push 0/imm32
15211     89/<- %edx 4/r32/esp
15212     (tailor-exit-descriptor %edx 0x10)
15213     #
15214     (write _test-input-stream "fn foo {\n")
15215     (write _test-input-stream "  var x/eax: int <- copy 0\n")
15216     (write _test-input-stream "  var y/ecx: int <- copy 0\n")
15217     (write _test-input-stream "  x, y <- convert 0\n")
15218     (write _test-input-stream "}\n")
15219     # convert
15220     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15221     # registers except esp clobbered at this point
15222     # restore ed
15223     89/<- %edx 4/r32/esp
15224     (flush _test-output-buffered-file)
15225     (flush _test-error-buffered-file)
15226 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15232     # check output
15233     (check-stream-equal _test-output-stream  ""  "F - test-convert-with-multiple-outputs: output should be empty")
15234     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'convert' must have just one output"  "F - test-convert-with-multiple-outputs: error message")
15235     # check that stop(1) was called
15236     (check-ints-equal *(edx+4) 2 "F - test-convert-with-multiple-outputs: exit status")
15237     # don't restore from ebp
15238     81 0/subop/add %esp 8/imm32
15239     # . epilogue
15240     5d/pop-to-ebp
15241     c3/return
15242 
15243 test-convert-deref-address:
15244     # . prologue
15245     55/push-ebp
15246     89/<- %ebp 4/r32/esp
15247     # setup
15248     (clear-stream _test-input-stream)
15249     (clear-stream $_test-input-buffered-file->buffer)
15250     (clear-stream _test-output-stream)
15251     (clear-stream $_test-output-buffered-file->buffer)
15252     #
15253     (write _test-input-stream "fn foo {\n")
15254     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
15255     (write _test-input-stream "  var y/xmm4: float <- convert *x\n")
15256     (write _test-input-stream "}\n")
15257     # convert
15258     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
15259     (flush _test-output-buffered-file)
15260     # no errors
15261     # . epilogue
15262     5d/pop-to-ebp
15263     c3/return
15264 
15265 test-convert-to-non-register:
15266     # . prologue
15267     55/push-ebp
15268     89/<- %ebp 4/r32/esp
15269     # setup
15270     (clear-stream _test-input-stream)
15271     (clear-stream $_test-input-buffered-file->buffer)
15272     (clear-stream _test-output-stream)
15273     (clear-stream $_test-output-buffered-file->buffer)
15274     (clear-stream _test-error-stream)
15275     (clear-stream $_test-error-buffered-file->buffer)
15276     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15277     68/push 0/imm32
15278     68/push 0/imm32
15279     89/<- %edx 4/r32/esp
15280     (tailor-exit-descriptor %edx 0x10)
15281     #
15282     (write _test-input-stream "fn foo {\n")
15283     (write _test-input-stream "  var x: float\n")
15284     (write _test-input-stream "  var y: int\n")
15285     (write _test-input-stream "  x <- convert y\n")
15286     (write _test-input-stream "}\n")
15287     # convert
15288     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15289     # registers except esp clobbered at this point
15290     # restore ed
15291     89/<- %edx 4/r32/esp
15292     (flush _test-output-buffered-file)
15293     (flush _test-error-buffered-file)
15294 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15300     # check output
15301     (check-stream-equal _test-output-stream  ""  "F - test-convert-to-non-register: output should be empty")
15302     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt convert: output 'x' not in a register"  "F - test-convert-to-non-register: error message")
15303     # check that stop(1) was called
15304     (check-ints-equal *(edx+4) 2 "F - test-convert-to-non-register: exit status")
15305     # don't restore from ebp
15306     81 0/subop/add %esp 8/imm32
15307     # . epilogue
15308     5d/pop-to-ebp
15309     c3/return
15310 
15311 test-convert-invalid-inout-type:
15312     # . prologue
15313     55/push-ebp
15314     89/<- %ebp 4/r32/esp
15315     # setup
15316     (clear-stream _test-input-stream)
15317     (clear-stream $_test-input-buffered-file->buffer)
15318     (clear-stream _test-output-stream)
15319     (clear-stream $_test-output-buffered-file->buffer)
15320     (clear-stream _test-error-stream)
15321     (clear-stream $_test-error-buffered-file->buffer)
15322     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15323     68/push 0/imm32
15324     68/push 0/imm32
15325     89/<- %edx 4/r32/esp
15326     (tailor-exit-descriptor %edx 0x10)
15327     #
15328     (write _test-input-stream "fn foo {\n")
15329     (write _test-input-stream "  var x: boolean\n")
15330     (write _test-input-stream "  var y/xmm1: float <- convert x\n")
15331     (write _test-input-stream "}\n")
15332     # convert
15333     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15334     # registers except esp clobbered at this point
15335     # restore ed
15336     89/<- %edx 4/r32/esp
15337     (flush _test-output-buffered-file)
15338     (flush _test-error-buffered-file)
15339 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15345     # check output
15346     (check-stream-equal _test-output-stream  ""  "F - test-convert-invalid-inout-type: output should be empty")
15347     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt convert: inout 'x' must be an int or float"  "F - test-convert-invalid-inout-type: error message")
15348     # check that stop(1) was called
15349     (check-ints-equal *(edx+4) 2 "F - test-convert-invalid-inout-type: exit status")
15350     # don't restore from ebp
15351     81 0/subop/add %esp 8/imm32
15352     # . epilogue
15353     5d/pop-to-ebp
15354     c3/return
15355 
15356 test-convert-invalid-output-type:
15357     # . prologue
15358     55/push-ebp
15359     89/<- %ebp 4/r32/esp
15360     # setup
15361     (clear-stream _test-input-stream)
15362     (clear-stream $_test-input-buffered-file->buffer)
15363     (clear-stream _test-output-stream)
15364     (clear-stream $_test-output-buffered-file->buffer)
15365     (clear-stream _test-error-stream)
15366     (clear-stream $_test-error-buffered-file->buffer)
15367     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15368     68/push 0/imm32
15369     68/push 0/imm32
15370     89/<- %edx 4/r32/esp
15371     (tailor-exit-descriptor %edx 0x10)
15372     #
15373     (write _test-input-stream "fn foo {\n")
15374     (write _test-input-stream "  var x: float\n")
15375     (write _test-input-stream "  var y/eax: boolean <- convert x\n")
15376     (write _test-input-stream "}\n")
15377     # convert
15378     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15379     # registers except esp clobbered at this point
15380     # restore ed
15381     89/<- %edx 4/r32/esp
15382     (flush _test-output-buffered-file)
15383     (flush _test-error-buffered-file)
15384 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15390     # check output
15391     (check-stream-equal _test-output-stream  ""  "F - test-convert-invalid-output-type: output should be empty")
15392     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt convert: output 'y' must be an int or float"  "F - test-convert-invalid-output-type: error message")
15393     # check that stop(1) was called
15394     (check-ints-equal *(edx+4) 2 "F - test-convert-invalid-output-type: exit status")
15395     # don't restore from ebp
15396     81 0/subop/add %esp 8/imm32
15397     # . epilogue
15398     5d/pop-to-ebp
15399     c3/return
15400 
15401 test-convert-int-to-int:
15402     # . prologue
15403     55/push-ebp
15404     89/<- %ebp 4/r32/esp
15405     # setup
15406     (clear-stream _test-input-stream)
15407     (clear-stream $_test-input-buffered-file->buffer)
15408     (clear-stream _test-output-stream)
15409     (clear-stream $_test-output-buffered-file->buffer)
15410     (clear-stream _test-error-stream)
15411     (clear-stream $_test-error-buffered-file->buffer)
15412     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15413     68/push 0/imm32
15414     68/push 0/imm32
15415     89/<- %edx 4/r32/esp
15416     (tailor-exit-descriptor %edx 0x10)
15417     #
15418     (write _test-input-stream "fn foo {\n")
15419     (write _test-input-stream "  var x: int\n")
15420     (write _test-input-stream "  var y/eax: int <- convert x\n")
15421     (write _test-input-stream "}\n")
15422     # convert
15423     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15424     # registers except esp clobbered at this point
15425     # restore ed
15426     89/<- %edx 4/r32/esp
15427     (flush _test-output-buffered-file)
15428     (flush _test-error-buffered-file)
15429 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15435     # check output
15436     (check-stream-equal _test-output-stream  ""  "F - test-convert-int-to-int: output should be empty")
15437     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt convert: no need to convert int to int"  "F - test-convert-int-to-int: error message")
15438     # check that stop(1) was called
15439     (check-ints-equal *(edx+4) 2 "F - test-convert-int-to-int: exit status")
15440     # don't restore from ebp
15441     81 0/subop/add %esp 8/imm32
15442     # . epilogue
15443     5d/pop-to-ebp
15444     c3/return
15445 
15446 test-convert-float-to-float:
15447     # . prologue
15448     55/push-ebp
15449     89/<- %ebp 4/r32/esp
15450     # setup
15451     (clear-stream _test-input-stream)
15452     (clear-stream $_test-input-buffered-file->buffer)
15453     (clear-stream _test-output-stream)
15454     (clear-stream $_test-output-buffered-file->buffer)
15455     (clear-stream _test-error-stream)
15456     (clear-stream $_test-error-buffered-file->buffer)
15457     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15458     68/push 0/imm32
15459     68/push 0/imm32
15460     89/<- %edx 4/r32/esp
15461     (tailor-exit-descriptor %edx 0x10)
15462     #
15463     (write _test-input-stream "fn foo {\n")
15464     (write _test-input-stream "  var x: float\n")
15465     (write _test-input-stream "  var y/xmm6: float <- convert x\n")
15466     (write _test-input-stream "}\n")
15467     # convert
15468     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15469     # registers except esp clobbered at this point
15470     # restore ed
15471     89/<- %edx 4/r32/esp
15472     (flush _test-output-buffered-file)
15473     (flush _test-error-buffered-file)
15474 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15480     # check output
15481     (check-stream-equal _test-output-stream  ""  "F - test-convert-float-to-float: output should be empty")
15482     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt convert: no need to convert float to float"  "F - test-convert-float-to-float: error message")
15483     # check that stop(1) was called
15484     (check-ints-equal *(edx+4) 2 "F - test-convert-float-to-float: exit status")
15485     # don't restore from ebp
15486     81 0/subop/add %esp 8/imm32
15487     # . epilogue
15488     5d/pop-to-ebp
15489     c3/return
15490 
15491 #######################################################
15492 # Parsing
15493 #######################################################
15494 
15495 == data
15496 
15497 # Global state added to each var record when parsing a function
15498 Next-block-index:  # (addr int)
15499     1/imm32
15500 
15501 Curr-block-depth:  # (addr int)
15502     1/imm32
15503 
15504 == code
15505 
15506 parse-mu:  # in: (addr buffered-file), err: (addr buffered-file), ed: (addr exit-descriptor)
15507     # pseudocode
15508     #   var curr-function: (addr handle function) = Program->functions
15509     #   var curr-signature: (addr handle function) = Program->signatures
15510     #   var curr-type: (addr handle typeinfo) = Program->types
15511     #   var line: (stream byte 512)
15512     #   var word-slice: slice
15513     #   while true                                  # line loop
15514     #     clear-stream(line)
15515     #     read-line-buffered(in, line)
15516     #     if (line->write == 0) break               # end of file
15517     #     word-slice = next-mu-token(line)
15518     #     if slice-empty?(word-slice)               # end of line
15519     #       continue
15520     #     else if slice-starts-with?(word-slice, "#")  # comment
15521     #       continue                                # end of line
15522     #     else if slice-equal?(word-slice, "fn")
15523     #       var new-function: (handle function) = allocate(function)
15524     #       var vars: (stack live-var 256)
15525     #       populate-mu-function-header(line, new-function, vars)
15526     #       populate-mu-function-body(in, new-function, vars)
15527     #       assert(vars->top == 0)
15528     #       *curr-function = new-function
15529     #       curr-function = &new-function->next
15530     #     else if slice-equal?(word-slice, "sig")
15531     #       var new-function: (handle function) = allocate(function)
15532     #       populate-mu-function-signature(line, new-function)
15533     #       *curr-signature = new-function
15534     #       curr-signature = &new-function->next
15535     #     else if slice-equal?(word-slice, "type")
15536     #       word-slice = next-mu-token(line)
15537     #       type-id = pos-or-insert-slice(Type-id, word-slice)
15538     #       var new-type: (handle typeinfo) = find-or-create-typeinfo(type-id)
15539     #       assert(next-word(line) == "{")
15540     #       populate-mu-type(in, new-type)
15541     #     else
15542     #       abort()
15543     #
15544     # . prologue
15545     55/push-ebp
15546     89/<- %ebp 4/r32/esp
15547     # var curr-signature: (addr handle function) at *(ebp-4)
15548     68/push _Program-signatures/imm32
15549     # . save registers
15550     50/push-eax
15551     51/push-ecx
15552     52/push-edx
15553     53/push-ebx
15554     56/push-esi
15555     57/push-edi
15556     # var line/ecx: (stream byte 512)
15557     81 5/subop/subtract %esp 0x200/imm32
15558     68/push 0x200/imm32/size
15559     68/push 0/imm32/read
15560     68/push 0/imm32/write
15561     89/<- %ecx 4/r32/esp
15562     # var word-slice/edx: slice
15563     68/push 0/imm32/end
15564     68/push 0/imm32/start
15565     89/<- %edx 4/r32/esp
15566     # var curr-function/edi: (addr handle function)
15567     bf/copy-to-edi _Program-functions/imm32
15568     # var vars/ebx: (stack live-var 256)
15569     81 5/subop/subtract %esp 0xc00/imm32
15570     68/push 0xc00/imm32/size
15571     68/push 0/imm32/top
15572     89/<- %ebx 4/r32/esp
15573     {
15574 $parse-mu:line-loop:
15575       (clear-stream %ecx)
15576       (read-line-buffered *(ebp+8) %ecx)
15577       # if (line->write == 0) break
15578       81 7/subop/compare *ecx 0/imm32
15579       0f 84/jump-if-= break/disp32
15580 +--  6 lines: #?       # dump line ------------------------------------------------------------------------------------------------------------------------------------------------------
15586       (next-mu-token %ecx %edx)
15587       # if slice-empty?(word-slice) continue
15588       (slice-empty? %edx)  # => eax
15589       3d/compare-eax-and 0/imm32/false
15590       0f 85/jump-if-!= loop/disp32
15591       # if (*word-slice->start == "#") continue
15592       # . eax = *word-slice->start
15593       8b/-> *edx 0/r32/eax
15594       8a/copy-byte *eax 0/r32/AL
15595       81 4/subop/and %eax 0xff/imm32
15596       # . if (eax == '#') continue
15597       3d/compare-eax-and 0x23/imm32/hash
15598       0f 84/jump-if-= loop/disp32
15599       # if (slice-equal?(word-slice, "fn")) parse a function
15600       {
15601 $parse-mu:fn:
15602         (slice-equal? %edx "fn")  # => eax
15603         3d/compare-eax-and 0/imm32/false
15604         0f 84/jump-if-= break/disp32
15605         # var new-function/esi: (handle function)
15606         68/push 0/imm32
15607         68/push 0/imm32
15608         89/<- %esi 4/r32/esp
15609         # populate-mu-function(line, in, vars, new-function)
15610         (allocate Heap *Function-size %esi)
15611         # var new-function-addr/eax: (addr function)
15612         (lookup *esi *(esi+4))  # => eax
15613         # initialize vars
15614         (clear-stack %ebx)
15615         #
15616         (populate-mu-function-header %ecx %eax %ebx *(ebp+0xc) *(ebp+0x10))
15617         (populate-mu-function-body *(ebp+8) %eax %ebx *(ebp+0xc) *(ebp+0x10))
15618         # *curr-function = new-function
15619         8b/-> *esi 0/r32/eax
15620         89/<- *edi 0/r32/eax
15621         8b/-> *(esi+4) 0/r32/eax
15622         89/<- *(edi+4) 0/r32/eax
15623         # curr-function = &new-function->next
15624         # . var tmp/eax: (addr function) = lookup(new-function)
15625         (lookup *esi *(esi+4))  # => eax
15626         # . curr-function = &tmp->next
15627         8d/copy-address *(eax+0x20) 7/r32/edi  # Function-next
15628         # reclaim new-function
15629         81 0/subop/add %esp 8/imm32
15630         #
15631         e9/jump $parse-mu:line-loop/disp32
15632       }
15633       # if (slice-equal?(word-slice, "sig")) parse a function signature
15634       # Function signatures are for providing types to SubX functions.
15635       {
15636 $parse-mu:sig:
15637         (slice-equal? %edx "sig")  # => eax
15638         3d/compare-eax-and 0/imm32/false
15639         0f 84/jump-if-= break/disp32
15640         # edi = curr-function
15641         57/push-edi
15642         8b/-> *(ebp-4) 7/r32/edi
15643         # var new-function/esi: (handle function)
15644         68/push 0/imm32
15645         68/push 0/imm32
15646         89/<- %esi 4/r32/esp
15647         # populate-mu-function(line, in, vars, new-function)
15648         (allocate Heap *Function-size %esi)
15649         # var new-function-addr/eax: (addr function)
15650         (lookup *esi *(esi+4))  # => eax
15651         #
15652         (populate-mu-function-signature %ecx %eax *(ebp+0xc) *(ebp+0x10))
15653         # *curr-signature = new-function
15654         8b/-> *esi 0/r32/eax
15655         89/<- *edi 0/r32/eax
15656         8b/-> *(esi+4) 0/r32/eax
15657         89/<- *(edi+4) 0/r32/eax
15658         # curr-signature = &new-function->next
15659         # . var tmp/eax: (addr function) = lookup(new-function)
15660         (lookup *esi *(esi+4))  # => eax
15661         # . curr-function = &tmp->next
15662         8d/copy-address *(eax+0x20) 7/r32/edi  # Function-next
15663         # reclaim new-function
15664         81 0/subop/add %esp 8/imm32
15665         # save curr-function
15666         89/<- *(ebp-4) 7/r32/edi
15667         # restore edi
15668         5f/pop-to-edi
15669         #
15670         e9/jump $parse-mu:line-loop/disp32
15671       }
15672       # if (slice-equal?(word-slice, "type")) parse a type (struct/record) definition
15673       {
15674 $parse-mu:type:
15675         (slice-equal? %edx "type")  # => eax
15676         3d/compare-eax-and 0/imm32
15677         0f 84/jump-if-= break/disp32
15678         (next-mu-token %ecx %edx)
15679         # var type-id/eax: int
15680         (pos-or-insert-slice Type-id %edx)  # => eax
15681         # spill
15682         51/push-ecx
15683         # var new-type/ecx: (handle typeinfo)
15684         68/push 0/imm32
15685         68/push 0/imm32
15686         89/<- %ecx 4/r32/esp
15687         (find-or-create-typeinfo %eax %ecx)
15688         #
15689         (lookup *ecx *(ecx+4))  # => eax
15690         # TODO: ensure that 'line' has nothing else but '{'
15691 #? (dump-typeinfos "=== aaa\n")
15692         (populate-mu-type *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10))  # => eax
15693 #? (dump-typeinfos "=== zzz\n")
15694         # reclaim new-type
15695         81 0/subop/add %esp 8/imm32
15696         # restore
15697         59/pop-to-ecx
15698         e9/jump $parse-mu:line-loop/disp32
15699       }
15700       # otherwise abort
15701       e9/jump $parse-mu:error1/disp32
15702     } # end line loop
15703 $parse-mu:end:
15704     # . reclaim locals
15705     81 0/subop/add %esp 0x20c/imm32  # line
15706     81 0/subop/add %esp 0xc08/imm32  # vars
15707     81 0/subop/add %esp 8/imm32
15708     # . restore registers
15709     5f/pop-to-edi
15710     5e/pop-to-esi
15711     5b/pop-to-ebx
15712     5a/pop-to-edx
15713     59/pop-to-ecx
15714     58/pop-to-eax
15715     # . reclaim local
15716     81 0/subop/add %esp 4/imm32
15717     # . epilogue
15718     89/<- %esp 5/r32/ebp
15719     5d/pop-to-ebp
15720     c3/return
15721 
15722 $parse-mu:error1:
15723     # error("unexpected top-level command: " word-slice "\n")
15724     (write-buffered *(ebp+0xc) "unexpected top-level command: ")
15725     (write-slice-buffered *(ebp+0xc) %edx)
15726     (write-buffered *(ebp+0xc) "\n")
15727     (flush *(ebp+0xc))
15728     (stop *(ebp+0x10) 1)
15729     # never gets here
15730 
15731 $parse-mu:error2:
15732     # error(vars->top " vars not reclaimed after fn '" new-function->name "'\n")
15733     (write-int32-hex-buffered *(ebp+0xc) *ebx)
15734     (write-buffered *(ebp+0xc) " vars not reclaimed after fn '")
15735     (write-slice-buffered *(ebp+0xc) *eax)  # Function-name
15736     (write-buffered *(ebp+0xc) "'\n")
15737     (flush *(ebp+0xc))
15738     (stop *(ebp+0x10) 1)
15739     # never gets here
15740 
15741 # scenarios considered:
15742 # ✗ fn foo  # no block
15743 # ✓ fn foo {
15744 # ✗ fn foo { {
15745 # ✗ fn foo { }
15746 # ✗ fn foo { } {
15747 # ✗ fn foo x {
15748 # ✗ fn foo x: {
15749 # ✓ fn foo x: int {
15750 # ✓ fn foo x: int {
15751 # ✓ fn foo x: int -> _/eax: int {
15752 # TODO:
15753 #   disallow outputs of type `(... addr ...)`
15754 #   disallow inputs of type `(... addr ... addr ...)`
15755 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)
15756     # pseudocode:
15757     #   var word-slice: slice
15758     #   next-mu-token(first-line, word-slice)
15759     #   if slice-empty?(word-slice) abort
15760     #   assert(word-slice not in '{' '}' '->')
15761     #   out->name = slice-to-string(word-slice)
15762     #   ## inouts
15763     #   while true
15764     #     word-slice = next-mu-token(first-line)
15765     #     if slice-empty?(word-slice) abort
15766     #     if (word-slice == '{') goto done
15767     #     if (word-slice == '->') break
15768     #     assert(word-slice != '}')
15769     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
15770     #     assert(v->register == null)
15771     #     # v->block-depth is implicitly 0
15772     #     out->inouts = append(v, out->inouts)
15773     #     push(vars, {v, false})
15774     #   ## outputs
15775     #   while true
15776     #     word-slice = next-mu-token(first-line)
15777     #     if slice-empty?(word-slice) abort
15778     #     if (word-slice == '{') break
15779     #     assert(word-slice not in '}' '->')
15780     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
15781     #     assert(v->register != null)
15782     #     assert(v->name == "_")
15783     #     out->outputs = append(v, out->outputs)
15784     #   done:
15785     #
15786     # . prologue
15787     55/push-ebp
15788     89/<- %ebp 4/r32/esp
15789     # . save registers
15790     50/push-eax
15791     51/push-ecx
15792     52/push-edx
15793     53/push-ebx
15794     57/push-edi
15795     # edi = out
15796     8b/-> *(ebp+0xc) 7/r32/edi
15797     # var word-slice/ecx: slice
15798     68/push 0/imm32/end
15799     68/push 0/imm32/start
15800     89/<- %ecx 4/r32/esp
15801     # var v/ebx: (handle var)
15802     68/push 0/imm32
15803     68/push 0/imm32
15804     89/<- %ebx 4/r32/esp
15805     # read function name
15806     (next-mu-token *(ebp+8) %ecx)
15807     # error checking
15808     # if slice-empty?(word-slice) abort
15809     (slice-empty? %ecx)  # => eax
15810     3d/compare-eax-and 0/imm32/false
15811     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
15812     # if (word-slice == '{') abort
15813     (slice-equal? %ecx "{")   # => eax
15814     3d/compare-eax-and 0/imm32/false
15815     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
15816     # if (word-slice == '->') abort
15817     (slice-equal? %ecx "->")   # => eax
15818     3d/compare-eax-and 0/imm32/false
15819     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
15820     # if (word-slice == '}') abort
15821     (slice-equal? %ecx "}")   # => eax
15822     3d/compare-eax-and 0/imm32/false
15823     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
15824     # if word-slice already defined, abort
15825     (function-exists? %ecx)  # => eax
15826     3d/compare-eax-and 0/imm32/false
15827     0f 85/jump-if-!= $populate-mu-function-header:error-duplicate/disp32
15828     #
15829     (slice-starts-with? %ecx "break")  # => eax
15830     3d/compare-eax-and 0/imm32/false
15831     0f 85/jump-if-!= $populate-mu-function-header:error-break/disp32
15832     (slice-starts-with? %ecx "loop")  # => eax
15833     3d/compare-eax-and 0/imm32/false
15834     0f 85/jump-if-!= $populate-mu-function-header:error-loop/disp32
15835     (slice-equal? %ecx "lookup")  # => eax
15836     3d/compare-eax-and 0/imm32/false
15837     0f 85/jump-if-!= $populate-mu-function-header:error-lookup/disp32
15838     # save function name
15839     (slice-to-string Heap %ecx %edi)  # Function-name
15840     # save function inouts
15841     {
15842 $populate-mu-function-header:check-for-inout:
15843       (next-mu-token *(ebp+8) %ecx)
15844       # if slice-empty?(word-slice) abort
15845       (slice-empty? %ecx)  # => eax
15846       3d/compare-eax-and 0/imm32/false
15847       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
15848       # if (word-slice == '{') goto done
15849       (slice-equal? %ecx "{")   # => eax
15850       3d/compare-eax-and 0/imm32/false
15851       0f 85/jump-if-!= $populate-mu-function-header:done/disp32
15852       # if (word-slice == '->') break
15853       (slice-equal? %ecx "->")   # => eax
15854       3d/compare-eax-and 0/imm32/false
15855       0f 85/jump-if-!= break/disp32
15856       # if (word-slice == '}') abort
15857       (slice-equal? %ecx "}")   # => eax
15858       3d/compare-eax-and 0/imm32/false
15859       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
15860       # v = parse-var-with-type(word-slice, first-line)
15861       (lookup *edi *(edi+4))  # Function-name Function-name => eax
15862       (parse-var-with-type %ecx *(ebp+8) %ebx %eax *(ebp+0x14) *(ebp+0x18))
15863       # if (v->register != null) abort
15864       # . eax: (addr var) = lookup(v)
15865       (lookup *ebx *(ebx+4))  # => eax
15866       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
15867       0f 85/jump-if-!= $populate-mu-function-header:error2/disp32
15868       # if function name is not "main"
15869       #    and v->type contains an 'addr' anywhere except the start, abort
15870       {
15871         (lookup *edi *(edi+4))  # Function-name Function-name => eax
15872         (string-equal? %eax "main")  # => eax
15873         3d/compare-eax-and 0/imm32/false
15874         75/jump-if-!= break/disp8
15875         (lookup *ebx *(ebx+4))  # => eax
15876         (addr-payload-contains-addr? %eax)  # => eax
15877         3d/compare-eax-and 0/imm32/false
15878         0f 85/jump-if-!= $populate-mu-function-header:error-nested-addr-inout/disp32
15879       }
15880       # v->block-depth is implicitly 0
15881       #
15882       # out->inouts = append(v, out->inouts)
15883       8d/copy-address *(edi+8) 0/r32/eax  # Function-inouts
15884       (append-list Heap  *ebx *(ebx+4)  *(edi+8) *(edi+0xc)  %eax)  # Function-inouts, Function-inouts
15885       # push(vars, {v, false})
15886       (push *(ebp+0x10) *ebx)
15887       (push *(ebp+0x10) *(ebx+4))
15888       (push *(ebp+0x10) 0)  # false
15889       #
15890       e9/jump loop/disp32
15891     }
15892     # save function outputs
15893     {
15894 $populate-mu-function-header:check-for-out:
15895       (next-mu-token *(ebp+8) %ecx)
15896       # if slice-empty?(word-slice) abort
15897       (slice-empty? %ecx)  # => eax
15898       3d/compare-eax-and 0/imm32/false
15899       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
15900       # if (word-slice == '{') break
15901       (slice-equal? %ecx "{")   # => eax
15902       3d/compare-eax-and 0/imm32/false
15903       0f 85/jump-if-!= break/disp32
15904       # if (word-slice == '->') abort
15905       (slice-equal? %ecx "->")   # => eax
15906       3d/compare-eax-and 0/imm32/false
15907       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
15908       # if (word-slice == '}') abort
15909       (slice-equal? %ecx "}")   # => eax
15910       3d/compare-eax-and 0/imm32/false
15911       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
15912       # v = parse-var-with-type(word-slice, first-line)
15913       (lookup *edi *(edi+4))  # Function-name Function-name => eax
15914       (parse-var-with-type %ecx *(ebp+8) %ebx %eax *(ebp+0x14) *(ebp+0x18))
15915       # assert(var->register != null)
15916       # . eax: (addr var) = lookup(v)
15917       (lookup *ebx *(ebx+4))  # => eax
15918       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
15919       0f 84/jump-if-= $populate-mu-function-header:error3/disp32
15920       # if (var->name != "_") abort
15921       (lookup *eax *(eax+4))  # Var-name Var-name => eax
15922       (string-equal? %eax "_")  # => eax
15923       3d/compare-eax-and 0/imm32/false
15924       0f 84/jump-if-= $populate-mu-function-header:error4/disp32
15925       # if v->type is an addr, abort
15926       (lookup *ebx *(ebx+4))  # => eax
15927       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
15928       (is-mu-addr-type? %eax)  # => eax
15929       3d/compare-eax-and 0/imm32/false
15930       0f 85/jump-if-!= $populate-mu-function-header:error-addr-output/disp32
15931       # out->outputs = append(v, out->outputs)
15932       8d/copy-address *(edi+0x10) 0/r32/eax  # Function-outputs
15933       (append-list Heap  *ebx *(ebx+4)  *(edi+0x10) *(edi+0x14)  %eax)  # Function-outputs, Function-outputs
15934       #
15935       e9/jump loop/disp32
15936     }
15937 $populate-mu-function-header:done:
15938     (check-no-tokens-left *(ebp+8))
15939 $populate-mu-function-header:end:
15940     # . reclaim locals
15941     81 0/subop/add %esp 0x10/imm32
15942     # . restore registers
15943     5f/pop-to-edi
15944     5b/pop-to-ebx
15945     5a/pop-to-edx
15946     59/pop-to-ecx
15947     58/pop-to-eax
15948     # . epilogue
15949     89/<- %esp 5/r32/ebp
15950     5d/pop-to-ebp
15951     c3/return
15952 
15953 $populate-mu-function-header:error1:
15954     # error("function header not in form 'fn <name> {'")
15955     (write-buffered *(ebp+0x14) "function header not in form 'fn <name> [inouts] [-> outputs] {' -- '")
15956     (flush *(ebp+0x14))
15957     (rewind-stream *(ebp+8))
15958     (write-stream-data *(ebp+0x14) *(ebp+8))
15959     (write-buffered *(ebp+0x14) "'\n")
15960     (flush *(ebp+0x14))
15961     (stop *(ebp+0x18) 1)
15962     # never gets here
15963 
15964 $populate-mu-function-header:error2:
15965     # error("fn " fn ": function inout '" var "' cannot be in a register")
15966     (write-buffered *(ebp+0x14) "fn ")
15967     50/push-eax
15968     (lookup *edi *(edi+4))  # Function-name Function-name => eax
15969     (write-buffered *(ebp+0x14) %eax)
15970     58/pop-to-eax
15971     (write-buffered *(ebp+0x14) ": function inout '")
15972     (lookup *eax *(eax+4))  # Var-name Var-name => eax
15973     (write-buffered *(ebp+0x14) %eax)
15974     (write-buffered *(ebp+0x14) "' cannot be in a register")
15975     (flush *(ebp+0x14))
15976     (stop *(ebp+0x18) 1)
15977     # never gets here
15978 
15979 $populate-mu-function-header:error3:
15980     # error("fn " fn ": function output '" var "' must be in a register")
15981     (write-buffered *(ebp+0x14) "fn ")
15982     50/push-eax
15983     (lookup *edi *(edi+4))  # Function-name Function-name => eax
15984     (write-buffered *(ebp+0x14) %eax)
15985     58/pop-to-eax
15986     (write-buffered *(ebp+0x14) ": function output '")
15987     (lookup *ebx *(ebx+4))  # => eax
15988     (lookup *eax *(eax+4))  # Var-name Var-name => eax
15989     (write-buffered *(ebp+0x14) %eax)
15990     (write-buffered *(ebp+0x14) "' must be in a register, in instruction '")
15991     (rewind-stream *(ebp+8))
15992     (write-stream-data *(ebp+0x14) *(ebp+8))
15993     (write-buffered *(ebp+0x14) "'\n")
15994     (flush *(ebp+0x14))
15995     (stop *(ebp+0x18) 1)
15996     # never gets here
15997 
15998 $populate-mu-function-header:error4:
15999     # error("fn " fn ": function outputs cannot be named; rename '" var "' in the header to '_'")
16000     (write-buffered *(ebp+0x14) "fn ")
16001     50/push-eax
16002     (lookup *edi *(edi+4))  # Function-name Function-name => eax
16003     (write-buffered *(ebp+0x14) %eax)
16004     58/pop-to-eax
16005     (write-buffered *(ebp+0x14) ": function outputs cannot be named; rename '")
16006     (lookup *ebx *(ebx+4))  # => eax
16007     (lookup *eax *(eax+4))  # Var-name Var-name => eax
16008     (write-buffered *(ebp+0x14) %eax)
16009     (write-buffered *(ebp+0x14) "' in the header to '_'\n")
16010     (flush *(ebp+0x14))
16011     (stop *(ebp+0x18) 1)
16012     # never gets here
16013 
16014 $populate-mu-function-header:error-duplicate:
16015     (write-buffered *(ebp+0x14) "fn ")
16016     (write-slice-buffered *(ebp+0x14) %ecx)
16017     (write-buffered *(ebp+0x14) " defined more than once\n")
16018     (flush *(ebp+0x14))
16019     (stop *(ebp+0x18) 1)
16020     # never gets here
16021 
16022 $populate-mu-function-header:error-break:
16023     (write-buffered *(ebp+0x14) "Sorry, I've reserved all function names starting with 'break' for now. Please contact mu@akkartik.com.\n")
16024     (flush *(ebp+0x14))
16025     (stop *(ebp+0x18) 1)
16026     # never gets here
16027 
16028 $populate-mu-function-header:error-loop:
16029     (write-buffered *(ebp+0x14) "Sorry, I've reserved all function names starting with 'loop' for now. Please contact mu@akkartik.com.\n")
16030     (flush *(ebp+0x14))
16031     (stop *(ebp+0x18) 1)
16032     # never gets here
16033 
16034 $populate-mu-function-header:error-lookup:
16035     (write-buffered *(ebp+0x14) "cannot define a function called 'lookup'\n")
16036     (flush *(ebp+0x14))
16037     (stop *(ebp+0x18) 1)
16038     # never gets here
16039 
16040 $populate-mu-function-header:error-addr-output:
16041     # error("fn " fn ": output cannot have an addr type; that could allow unsafe addresses to escape the function")
16042     (write-buffered *(ebp+0x14) "fn ")
16043     50/push-eax
16044     (lookup *edi *(edi+4))  # Function-name Function-name => eax
16045     (write-buffered *(ebp+0x14) %eax)
16046     58/pop-to-eax
16047     (write-buffered *(ebp+0x14) ": output cannot have an addr type; that could allow unsafe addresses to escape the function\n")
16048     (flush *(ebp+0x14))
16049     (stop *(ebp+0x18) 1)
16050     # never gets here
16051 
16052 $populate-mu-function-header:error-nested-addr-inout:
16053     # error("fn " fn ": inout '" var "' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function")
16054     (write-buffered *(ebp+0x14) "fn ")
16055     (lookup *edi *(edi+4))  # Function-name Function-name => eax
16056     (write-buffered *(ebp+0x14) %eax)
16057     (write-buffered *(ebp+0x14) ": inout '")
16058     (lookup *ebx *(ebx+4))  # => eax
16059     (lookup *eax *(eax+4))  # Var-name Var-name => eax
16060     (write-buffered *(ebp+0x14) %eax)
16061     (write-buffered *(ebp+0x14) "' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function\n")
16062     (flush *(ebp+0x14))
16063     (stop *(ebp+0x18) 1)
16064     # never gets here
16065 
16066 # scenarios considered:
16067 # ✓ fn foo
16068 # ✗ fn foo {
16069 # ✓ fn foo x
16070 # ✓ fn foo x: int
16071 # ✓ fn foo x: int -> _/eax: int
16072 # TODO:
16073 #   disallow outputs of type `(... addr ...)`
16074 #   disallow inputs of type `(... addr ... addr ...)`
16075 populate-mu-function-signature:  # first-line: (addr stream byte), out: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
16076     # pseudocode:
16077     #   var word-slice: slice
16078     #   next-mu-token(first-line, word-slice)
16079     #   assert(word-slice not in '{' '}' '->')
16080     #   out->name = slice-to-string(word-slice)
16081     #   ## inouts
16082     #   while true
16083     #     word-slice = next-mu-token(first-line)
16084     #     if slice-empty?(word-slice) break
16085     #     if (word-slice == '->') break
16086     #     assert(word-slice not in '{' '}')
16087     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
16088     #     assert(v->register == null)
16089     #     # v->block-depth is implicitly 0
16090     #     out->inouts = append(v, out->inouts)
16091     #   ## outputs
16092     #   while true
16093     #     word-slice = next-mu-token(first-line)
16094     #     if slice-empty?(word-slice) break
16095     #     assert(word-slice not in '{' '}' '->')
16096     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
16097     #     assert(v->register != null)
16098     #     out->outputs = append(v, out->outputs)
16099     #
16100     # . prologue
16101     55/push-ebp
16102     89/<- %ebp 4/r32/esp
16103     # . save registers
16104     50/push-eax
16105     51/push-ecx
16106     52/push-edx
16107     53/push-ebx
16108     57/push-edi
16109     # edi = out
16110     8b/-> *(ebp+0xc) 7/r32/edi
16111     # var word-slice/ecx: slice
16112     68/push 0/imm32/end
16113     68/push 0/imm32/start
16114     89/<- %ecx 4/r32/esp
16115     # var v/ebx: (handle var)
16116     68/push 0/imm32
16117     68/push 0/imm32
16118     89/<- %ebx 4/r32/esp
16119     # read function name
16120     (next-mu-token *(ebp+8) %ecx)
16121     # error checking
16122     # if (word-slice == '{') abort
16123     (slice-equal? %ecx "{")   # => eax
16124     3d/compare-eax-and 0/imm32/false
16125     0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
16126     # if (word-slice == '->') abort
16127     (slice-equal? %ecx "->")   # => eax
16128     3d/compare-eax-and 0/imm32/false
16129     0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
16130     # if (word-slice == '}') abort
16131     (slice-equal? %ecx "}")   # => eax
16132     3d/compare-eax-and 0/imm32/false
16133     0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
16134     # if word-slice already defined, abort
16135     (function-exists? %ecx)  # => eax
16136     3d/compare-eax-and 0/imm32/false
16137     0f 85/jump-if-!= $populate-mu-function-signature:error-duplicate/disp32
16138     #
16139     (slice-starts-with? %ecx "break")  # => eax
16140     3d/compare-eax-and 0/imm32/false
16141     0f 85/jump-if-!= $populate-mu-function-signature:error-break/disp32
16142     (slice-starts-with? %ecx "loop")  # => eax
16143     3d/compare-eax-and 0/imm32/false
16144     0f 85/jump-if-!= $populate-mu-function-signature:error-loop/disp32
16145     # save function name
16146     (slice-to-string Heap %ecx %edi)  # Function-name
16147     # save function inouts
16148     {
16149 $populate-mu-function-signature:check-for-inout:
16150       (next-mu-token *(ebp+8) %ecx)
16151       (slice-empty? %ecx)  # => eax
16152       3d/compare-eax-and 0/imm32/false
16153       0f 85/jump-if-!= break/disp32
16154       # if (word-slice == '->') break
16155       (slice-equal? %ecx "->")   # => eax
16156       3d/compare-eax-and 0/imm32/false
16157       0f 85/jump-if-!= break/disp32
16158       # if (word-slice == '{') abort
16159       (slice-equal? %ecx "{")   # => eax
16160       3d/compare-eax-and 0/imm32/false
16161       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
16162       # if (word-slice == '}') abort
16163       (slice-equal? %ecx "}")   # => eax
16164       3d/compare-eax-and 0/imm32/false
16165       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
16166       # v = parse-var-with-type(word-slice, first-line)
16167       (lookup *edi *(edi+4))  # Function-name Function-name => eax
16168       (parse-var-with-type %ecx *(ebp+8) %ebx %eax *(ebp+0x10) *(ebp+0x14))
16169       # if (v->register != null) abort
16170       # . eax: (addr var) = lookup(v)
16171       (lookup *ebx *(ebx+4))  # => eax
16172       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
16173       0f 85/jump-if-!= $populate-mu-function-signature:error2/disp32
16174       # if function name is not "main"
16175       #    and v->type contains an 'addr' anywhere except the start, abort
16176       {
16177         (lookup *edi *(edi+4))  # Function-name Function-name => eax
16178         (string-equal? %eax "main")  # => eax
16179         3d/compare-eax-and 0/imm32/false
16180         75/jump-if-!= break/disp8
16181         (lookup *ebx *(ebx+4))  # => eax
16182         (addr-payload-contains-addr? %eax)  # => eax
16183         3d/compare-eax-and 0/imm32/false
16184         0f 85/jump-if-!= $populate-mu-function-signature:error-nested-addr-inout/disp32
16185       }
16186       # assert(v->register == null)
16187       # . eax: (addr var) = lookup(v)
16188       (lookup *ebx *(ebx+4))  # => eax
16189       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
16190       0f 85/jump-if-!= $populate-mu-function-signature:error2/disp32
16191       # v->block-depth is implicitly 0
16192       #
16193       # out->inouts = append(v, out->inouts)
16194       8d/copy-address *(edi+8) 0/r32/eax  # Function-inouts
16195       (append-list Heap  *ebx *(ebx+4)  *(edi+8) *(edi+0xc)  %eax)  # Function-inouts, Function-inouts
16196       #
16197       e9/jump loop/disp32
16198     }
16199     # save function outputs
16200     {
16201 $populate-mu-function-signature:check-for-out:
16202       (next-mu-token *(ebp+8) %ecx)
16203       (slice-empty? %ecx)  # => eax
16204       3d/compare-eax-and 0/imm32/false
16205       0f 85/jump-if-!= break/disp32
16206       # if (word-slice == '{') abort
16207       (slice-equal? %ecx "{")   # => eax
16208       3d/compare-eax-and 0/imm32/false
16209       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
16210       # if (word-slice == '->') abort
16211       (slice-equal? %ecx "->")   # => eax
16212       3d/compare-eax-and 0/imm32/false
16213       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
16214       # if (word-slice == '}') abort
16215       (slice-equal? %ecx "}")   # => eax
16216       3d/compare-eax-and 0/imm32/false
16217       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
16218       # v = parse-var-with-type(word-slice, first-line)
16219       (lookup *edi *(edi+4))  # Function-name Function-name => eax
16220       (parse-var-with-type %ecx *(ebp+8) %ebx %eax *(ebp+0x10) *(ebp+0x14))
16221       # assert(var->register != null)
16222       # . eax: (addr var) = lookup(v)
16223       (lookup *ebx *(ebx+4))  # => eax
16224       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
16225       0f 84/jump-if-= $populate-mu-function-signature:error3/disp32
16226       # if (var->name != "_") abort
16227       (lookup *eax *(eax+4))  # Var-name Var-name => eax
16228       (string-equal? %eax "_")  # => eax
16229       3d/compare-eax-and 0/imm32/false
16230       0f 84/jump-if-= $populate-mu-function-signature:error4/disp32
16231       # if function name is not "lookup"
16232       #    and v->type is an addr, abort
16233       {
16234         (lookup *edi *(edi+4))  # Function-name Function-name => eax
16235         (string-equal? %eax "lookup")  # => eax
16236         3d/compare-eax-and 0/imm32/false
16237         75/jump-if-!= break/disp8
16238         (lookup *ebx *(ebx+4))  # => eax
16239         (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
16240         (is-mu-addr-type? %eax)  # => eax
16241         3d/compare-eax-and 0/imm32/false
16242         0f 85/jump-if-!= $populate-mu-function-signature:error-addr-output/disp32
16243       }
16244       # out->outputs = append(v, out->outputs)
16245       8d/copy-address *(edi+0x10) 0/r32/eax  # Function-outputs
16246       (append-list Heap  *ebx *(ebx+4)  *(edi+0x10) *(edi+0x14)  %eax)  # Function-outputs, Function-outputs
16247       #
16248       e9/jump loop/disp32
16249     }
16250 $populate-mu-function-signature:done:
16251     (check-no-tokens-left *(ebp+8))
16252 $populate-mu-function-signature:end:
16253     # . reclaim locals
16254     81 0/subop/add %esp 0x10/imm32
16255     # . restore registers
16256     5f/pop-to-edi
16257     5b/pop-to-ebx
16258     5a/pop-to-edx
16259     59/pop-to-ecx
16260     58/pop-to-eax
16261     # . epilogue
16262     89/<- %esp 5/r32/ebp
16263     5d/pop-to-ebp
16264     c3/return
16265 
16266 $populate-mu-function-signature:error1:
16267     # error("function signature not in form 'fn <name> {'")
16268     (write-buffered *(ebp+0x10) "function signature not in form 'fn <name> [inouts] [-> outputs] {' -- '")
16269     (flush *(ebp+0x10))
16270     (rewind-stream *(ebp+8))
16271     (write-stream-data *(ebp+0x10) *(ebp+8))
16272     (write-buffered *(ebp+0x10) "'\n")
16273     (flush *(ebp+0x10))
16274     (stop *(ebp+0x14) 1)
16275     # never gets here
16276 
16277 $populate-mu-function-signature:error2:
16278     # error("fn " fn ": function inout '" var "' cannot be in a register")
16279     (write-buffered *(ebp+0x10) "fn ")
16280     50/push-eax
16281     (lookup *edi *(edi+4))  # Function-name Function-name => eax
16282     (write-buffered *(ebp+0x10) %eax)
16283     58/pop-to-eax
16284     (write-buffered *(ebp+0x10) ": function inout '")
16285     (lookup *eax *(eax+4))  # Var-name Var-name => eax
16286     (write-buffered *(ebp+0x10) %eax)
16287     (write-buffered *(ebp+0x10) "' cannot be in a register")
16288     (flush *(ebp+0x10))
16289     (stop *(ebp+0x14) 1)
16290     # never gets here
16291 
16292 $populate-mu-function-signature:error3:
16293     # error("fn " fn ": function output '" var "' must be in a register")
16294     (write-buffered *(ebp+0x10) "fn ")
16295     50/push-eax
16296     (lookup *edi *(edi+4))  # Function-name Function-name => eax
16297     (write-buffered *(ebp+0x10) %eax)
16298     58/pop-to-eax
16299     (write-buffered *(ebp+0x10) ": function output '")
16300     (lookup *ebx *(ebx+4))  # => eax
16301     (lookup *eax *(eax+4))  # Var-name Var-name => eax
16302     (write-buffered *(ebp+0x10) %eax)
16303     (write-buffered *(ebp+0x10) "' must be in a register, in instruction '")
16304     (rewind-stream *(ebp+8))
16305     (write-stream-data *(ebp+0x10) *(ebp+8))
16306     (write-buffered *(ebp+0x10) "'\n")
16307     (flush *(ebp+0x10))
16308     (stop *(ebp+0x14) 1)
16309     # never gets here
16310 
16311 $populate-mu-function-signature:error4:
16312     # error("fn " fn ": function outputs cannot be named; rename '" var "' in the header to '_'")
16313     (write-buffered *(ebp+0x10) "fn ")
16314     50/push-eax
16315     (lookup *edi *(edi+4))  # Function-name Function-name => eax
16316     (write-buffered *(ebp+0x10) %eax)
16317     58/pop-to-eax
16318     (write-buffered *(ebp+0x10) ": function outputs cannot be named; rename '")
16319     (lookup *ebx *(ebx+4))  # => eax
16320     (lookup *eax *(eax+4))  # Var-name Var-name => eax
16321     (write-buffered *(ebp+0x10) %eax)
16322     (write-buffered *(ebp+0x10) "' in the header to '_'\n")
16323     (flush *(ebp+0x10))
16324     (stop *(ebp+0x14) 1)
16325     # never gets here
16326 
16327 $populate-mu-function-signature:error-duplicate:
16328     (write-buffered *(ebp+0x10) "fn ")
16329     (write-slice-buffered *(ebp+0x10) %ecx)
16330     (write-buffered *(ebp+0x10) " defined more than once\n")
16331     (flush *(ebp+0x10))
16332     (stop *(ebp+0x14) 1)
16333     # never gets here
16334 
16335 $populate-mu-function-signature:error-break:
16336     (write-buffered *(ebp+0x10) "Sorry, I've reserved all function names starting with 'break' for now. Please contact mu@akkartik.com.\n")
16337     (flush *(ebp+0x10))
16338     (stop *(ebp+0x14) 1)
16339     # never gets here
16340 
16341 $populate-mu-function-signature:error-loop:
16342     (write-buffered *(ebp+0x10) "Sorry, I've reserved all function names starting with 'loop' for now. Please contact mu@akkartik.com.\n")
16343     (flush *(ebp+0x10))
16344     (stop *(ebp+0x14) 1)
16345     # never gets here
16346 
16347 $populate-mu-function-signature:error-addr-output:
16348     # error("fn " fn ": output cannot have an addr type; that could allow unsafe addresses to escape the function")
16349     (write-buffered *(ebp+0x10) "fn ")
16350     50/push-eax
16351     (lookup *edi *(edi+4))  # Function-name Function-name => eax
16352     (write-buffered *(ebp+0x10) %eax)
16353     58/pop-to-eax
16354     (write-buffered *(ebp+0x10) ": output cannot have an addr type; that could allow unsafe addresses to escape the function\n")
16355     (flush *(ebp+0x10))
16356     (stop *(ebp+0x14) 1)
16357     # never gets here
16358 
16359 $populate-mu-function-signature:error-nested-addr-inout:
16360     # error("fn " fn ": inout '" var "' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function")
16361     (write-buffered *(ebp+0x10) "fn ")
16362     (lookup *edi *(edi+4))  # Function-name Function-name => eax
16363     (write-buffered *(ebp+0x10) %eax)
16364     (write-buffered *(ebp+0x10) ": inout '")
16365     (lookup *ebx *(ebx+4))  # => eax
16366     (lookup *eax *(eax+4))  # Var-name Var-name => eax
16367     (write-buffered *(ebp+0x10) %eax)
16368     (write-buffered *(ebp+0x10) "' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function\n")
16369     (flush *(ebp+0x10))
16370     (stop *(ebp+0x14) 1)
16371     # never gets here
16372 
16373 addr-payload-contains-addr?:  # v: (addr var) -> result/eax: boolean
16374     # . prologue
16375     55/push-ebp
16376     89/<- %ebp 4/r32/esp
16377     # var t/eax: (addr type-tree) = v->type
16378     8b/-> *(ebp+8) 0/r32/eax
16379     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
16380     # if t->right contains addr, return true
16381     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
16382     (type-tree-contains? %eax 2)  # addr => eax
16383     # we don't have to look at t->left as long as it's guaranteed to be an atom
16384 $addr-payload-contains-addr?:end:
16385     # . epilogue
16386     89/<- %esp 5/r32/ebp
16387     5d/pop-to-ebp
16388     c3/return
16389 
16390 type-tree-contains?:  # t: (addr type-tree), n: type-id -> result/eax: boolean
16391     # . prologue
16392     55/push-ebp
16393     89/<- %ebp 4/r32/esp
16394     # . save registers
16395     51/push-ecx
16396     # if t is null, return false
16397     8b/-> *(ebp+8) 0/r32/eax
16398     3d/compare-eax-and 0/imm32
16399     0f 84/jump-if-= $type-tree-contains?:end/disp32  # eax changes type
16400     # if t is an atom, return (t->value == n)
16401     81 7/subop/compare *eax 0/imm32/false
16402     {
16403       74/jump-if-= break/disp8
16404       8b/-> *(ebp+0xc) 1/r32/ecx
16405       39/compare *(eax+4) 1/r32/ecx  # Type-tree-value
16406       0f 94/set-if-= %al
16407       81 4/subop/and %eax 0xff/imm32
16408       eb/jump $type-tree-contains?:end/disp8
16409     }
16410     # if t->left contains n, return true
16411     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
16412     (type-tree-contains? %eax *(ebp+0xc))  # => eax
16413     3d/compare-eax-and 0/imm32/false
16414     75/jump-if-!= $type-tree-contains?:end/disp8
16415     # otherwise return whether t->right contains n
16416     8b/-> *(ebp+8) 0/r32/eax
16417     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
16418     (type-tree-contains? %eax *(ebp+0xc))  # => eax
16419 $type-tree-contains?:end:
16420     # . restore registers
16421     59/pop-to-ecx
16422     # . epilogue
16423     89/<- %esp 5/r32/ebp
16424     5d/pop-to-ebp
16425     c3/return
16426 
16427 function-exists?:  # s: (addr slice) -> result/eax: boolean
16428     # . prologue
16429     55/push-ebp
16430     89/<- %ebp 4/r32/esp
16431     # . save registers
16432     51/push-ecx
16433     # var curr/ecx: (addr function) = functions
16434     (lookup *_Program-functions *_Program-functions->payload)  # => eax
16435     89/<- %ecx 0/r32/eax
16436     {
16437       # if (curr == null) break
16438       81 7/subop/compare %ecx 0/imm32
16439       74/jump-if-= break/disp8
16440       # if (curr->name == s) return true
16441       {
16442         (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
16443         (slice-equal? *(ebp+8) %eax)  # => eax
16444         3d/compare-eax-and 0/imm32/false
16445         74/jump-if-= break/disp8
16446         b8/copy-to-eax 1/imm32/true
16447         e9/jump $function-exists?:end/disp32
16448       }
16449       # curr = curr->next
16450       (lookup *(ecx+0x20) *(ecx+0x24))  # Function-next Function-next => eax
16451       89/<- %ecx 0/r32/eax
16452       #
16453       eb/jump loop/disp8
16454     }
16455     # var curr/ecx: (addr function) = signatures
16456     (lookup *_Program-signatures *_Program-signatures->payload)  # => eax
16457     89/<- %ecx 0/r32/eax
16458     {
16459       # if (curr == null) break
16460       81 7/subop/compare %ecx 0/imm32
16461       74/jump-if-= break/disp8
16462       # if (curr->name == s) return true
16463       {
16464         (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
16465         (slice-equal? *(ebp+8) %eax)  # => eax
16466         3d/compare-eax-and 0/imm32/false
16467         74/jump-if-= break/disp8
16468         b8/copy-to-eax 1/imm32/true
16469         eb/jump $function-exists?:end/disp8
16470       }
16471       # curr = curr->next
16472       (lookup *(ecx+0x20) *(ecx+0x24))  # Function-next Function-next => eax
16473       89/<- %ecx 0/r32/eax
16474       #
16475       eb/jump loop/disp8
16476     }
16477     # return false
16478     b8/copy-to-eax 0/imm32/false
16479 $function-exists?:end:
16480     # . restore registers
16481     59/pop-to-ecx
16482     # . epilogue
16483     89/<- %esp 5/r32/ebp
16484     5d/pop-to-ebp
16485     c3/return
16486 
16487 test-function-header-with-arg:
16488     # . prologue
16489     55/push-ebp
16490     89/<- %ebp 4/r32/esp
16491     # setup
16492     8b/-> *Primitive-type-ids 0/r32/eax
16493     89/<- *Type-id 0/r32/eax  # stream-write
16494     c7 0/subop/copy *_Program-functions 0/imm32
16495     c7 0/subop/copy *_Program-functions->payload 0/imm32
16496     c7 0/subop/copy *_Program-types 0/imm32
16497     c7 0/subop/copy *_Program-types->payload 0/imm32
16498     c7 0/subop/copy *_Program-signatures 0/imm32
16499     c7 0/subop/copy *_Program-signatures->payload 0/imm32
16500     (clear-stream _test-input-stream)
16501     (write _test-input-stream "foo n: int {\n")
16502     # var result/ecx: function
16503     2b/subtract *Function-size 4/r32/esp
16504     89/<- %ecx 4/r32/esp
16505     (zero-out %ecx *Function-size)
16506     # var vars/ebx: (stack live-var 16)
16507     81 5/subop/subtract %esp 0xc0/imm32
16508     68/push 0xc0/imm32/size
16509     68/push 0/imm32/top
16510     89/<- %ebx 4/r32/esp
16511     # convert
16512     (populate-mu-function-header _test-input-stream %ecx %ebx Stderr 0)
16513     # check result->name
16514     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
16515     (check-strings-equal %eax "foo" "F - test-function-header-with-arg/name")
16516     # var v/edx: (addr var) = result->inouts->value
16517     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
16518     (lookup *eax *(eax+4))  # List-value List-value => eax
16519     89/<- %edx 0/r32/eax
16520     # check v->name
16521     (lookup *edx *(edx+4))  # Var-name Var-name => eax
16522     (check-strings-equal %eax "n" "F - test-function-header-with-arg/inout:0")
16523     # check v->type
16524     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
16525     (check-ints-equal *eax 1 "F - test-function-header-with-arg/inout:0/type:0")  # Type-tree-is-atom
16526     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-arg/inout:0/type:1")  # Type-tree-value
16527     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-arg/inout:0/type:2")  # Type-tree-right
16528     # . epilogue
16529     89/<- %esp 5/r32/ebp
16530     5d/pop-to-ebp
16531     c3/return
16532 
16533 test-function-header-with-multiple-args:
16534     # . prologue
16535     55/push-ebp
16536     89/<- %ebp 4/r32/esp
16537     # setup
16538     8b/-> *Primitive-type-ids 0/r32/eax
16539     89/<- *Type-id 0/r32/eax  # stream-write
16540     c7 0/subop/copy *_Program-functions 0/imm32
16541     c7 0/subop/copy *_Program-functions->payload 0/imm32
16542     c7 0/subop/copy *_Program-types 0/imm32
16543     c7 0/subop/copy *_Program-types->payload 0/imm32
16544     c7 0/subop/copy *_Program-signatures 0/imm32
16545     c7 0/subop/copy *_Program-signatures->payload 0/imm32
16546     (clear-stream _test-input-stream)
16547     (write _test-input-stream "foo a: int, b: int c: int {\n")
16548     # result/ecx: function
16549     2b/subtract *Function-size 4/r32/esp
16550     89/<- %ecx 4/r32/esp
16551     (zero-out %ecx *Function-size)
16552     # var vars/ebx: (stack live-var 16)
16553     81 5/subop/subtract %esp 0xc0/imm32
16554     68/push 0xc0/imm32/size
16555     68/push 0/imm32/top
16556     89/<- %ebx 4/r32/esp
16557     # convert
16558     (populate-mu-function-header _test-input-stream %ecx %ebx Stderr 0)
16559     # check result->name
16560     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
16561     (check-strings-equal %eax "foo" "F - test-function-header-with-multiple-args/name")
16562     # var inouts/edx: (addr list var) = lookup(result->inouts)
16563     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
16564     89/<- %edx 0/r32/eax
16565 $test-function-header-with-multiple-args:inout0:
16566     # var v/ebx: (addr var) = lookup(inouts->value)
16567     (lookup *edx *(edx+4))  # List-value List-value => eax
16568     89/<- %ebx 0/r32/eax
16569     # check v->name
16570     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
16571     (check-strings-equal %eax "a" "F - test-function-header-with-multiple-args/inout:0")  # Var-name
16572     # check v->type
16573     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
16574     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args/inout:0/type:0")  # Type-tree-is-atom
16575     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args/inout:0/type:1")  # Type-tree-value
16576     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args/inout:0/type:2")  # Type-tree-right
16577 $test-function-header-with-multiple-args:inout1:
16578     # inouts = lookup(inouts->next)
16579     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
16580     89/<- %edx 0/r32/eax
16581     # v = lookup(inouts->value)
16582     (lookup *edx *(edx+4))  # List-value List-value => eax
16583     89/<- %ebx 0/r32/eax
16584     # check v->name
16585     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
16586     (check-strings-equal %eax "b" "F - test-function-header-with-multiple-args/inout:1")  # Var-name
16587     # check v->type
16588     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
16589     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args/inout:1/type:0")  # Type-tree-is-atom
16590     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args/inout:1/type:1")  # Type-tree-value
16591     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args/inout:1/type:2")  # Type-tree-right
16592 $test-function-header-with-multiple-args:inout2:
16593     # inouts = lookup(inouts->next)
16594     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
16595     89/<- %edx 0/r32/eax
16596     # v = lookup(inouts->value)
16597     (lookup *edx *(edx+4))  # List-value List-value => eax
16598     89/<- %ebx 0/r32/eax
16599     # check v->name
16600     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
16601     (check-strings-equal %eax "c" "F - test-function-header-with-multiple-args/inout:2")  # Var-name
16602     # check v->type
16603     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
16604     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args/inout:2/type:0")  # Type-tree-is-atom
16605     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args/inout:2/type:1")  # Type-tree-value
16606     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args/inout:2/type:2")  # Type-tree-right
16607     # . epilogue
16608     89/<- %esp 5/r32/ebp
16609     5d/pop-to-ebp
16610     c3/return
16611 
16612 test-function-header-with-multiple-args-and-outputs:
16613     # . prologue
16614     55/push-ebp
16615     89/<- %ebp 4/r32/esp
16616     # setup
16617     8b/-> *Primitive-type-ids 0/r32/eax
16618     89/<- *Type-id 0/r32/eax  # stream-write
16619     c7 0/subop/copy *_Program-functions 0/imm32
16620     c7 0/subop/copy *_Program-functions->payload 0/imm32
16621     c7 0/subop/copy *_Program-types 0/imm32
16622     c7 0/subop/copy *_Program-types->payload 0/imm32
16623     c7 0/subop/copy *_Program-signatures 0/imm32
16624     c7 0/subop/copy *_Program-signatures->payload 0/imm32
16625     (clear-stream _test-input-stream)
16626     (write _test-input-stream "foo a: int, b: int, c: int -> _/ecx: int _/edx: int {\n")
16627     # result/ecx: function
16628     2b/subtract *Function-size 4/r32/esp
16629     89/<- %ecx 4/r32/esp
16630     (zero-out %ecx *Function-size)
16631     # var vars/ebx: (stack live-var 16)
16632     81 5/subop/subtract %esp 0xc0/imm32
16633     68/push 0xc0/imm32/size
16634     68/push 0/imm32/top
16635     89/<- %ebx 4/r32/esp
16636     # convert
16637     (populate-mu-function-header _test-input-stream %ecx %ebx Stderr 0)
16638     # check result->name
16639     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
16640     (check-strings-equal %eax "foo" "F - test-function-header-with-multiple-args-and-outputs/name")
16641     # var inouts/edx: (addr list var) = lookup(result->inouts)
16642     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
16643     89/<- %edx 0/r32/eax
16644 $test-function-header-with-multiple-args-and-outputs:inout0:
16645     # var v/ebx: (addr var) = lookup(inouts->value)
16646     (lookup *edx *(edx+4))  # List-value List-value => eax
16647     89/<- %ebx 0/r32/eax
16648     # check v->name
16649     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
16650     (check-strings-equal %eax "a" "F - test-function-header-with-multiple-args-and-outputs/inout:0")
16651     # check v->type
16652     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
16653     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:0")  # Type-tree-is-atom
16654     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:1")  # Type-tree-value
16655     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:2")  # Type-tree-right
16656 $test-function-header-with-multiple-args-and-outputs:inout1:
16657     # inouts = lookup(inouts->next)
16658     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
16659     89/<- %edx 0/r32/eax
16660     # v = lookup(inouts->value)
16661     (lookup *edx *(edx+4))  # List-value List-value => eax
16662     89/<- %ebx 0/r32/eax
16663     # check v->name
16664     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
16665     (check-strings-equal %eax "b" "F - test-function-header-with-multiple-args-and-outputs/inout:1")
16666     # check v->type
16667     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
16668     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:0")  # Type-tree-is-atom
16669     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:1")  # Type-tree-value
16670     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:2")  # Type-tree-right
16671 $test-function-header-with-multiple-args-and-outputs:inout2:
16672     # inouts = lookup(inouts->next)
16673     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
16674     89/<- %edx 0/r32/eax
16675     # v = lookup(inouts->value)
16676     (lookup *edx *(edx+4))  # List-value List-value => eax
16677     89/<- %ebx 0/r32/eax
16678     # check v->name
16679     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
16680     (check-strings-equal %eax "c" "F - test-function-header-with-multiple-args-and-outputs/inout:2")
16681     # check v->type
16682     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
16683     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:0")  # Type-tree-is-atom
16684     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:1")  # Type-tree-value
16685     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:2")  # Type-tree-right
16686 $test-function-header-with-multiple-args-and-outputs:out0:
16687     # var outputs/edx: (addr list var) = lookup(result->outputs)
16688     (lookup *(ecx+0x10) *(ecx+0x14))  # Function-outputs Function-outputs => eax
16689     89/<- %edx 0/r32/eax
16690     # v = lookup(outputs->value)
16691     (lookup *edx *(edx+4))  # List-value List-value => eax
16692     89/<- %ebx 0/r32/eax
16693     # check v->name
16694     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
16695     (check-strings-equal %eax "_" "F - test-function-header-with-multiple-args-and-outputs/output:0")
16696     # check v->register
16697     (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
16698     (check-strings-equal %eax "ecx" "F - test-function-header-with-multiple-args-and-outputs/output:0/register")
16699     # check v->type
16700     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
16701     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:0")  # Type-tree-is-atom
16702     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:1")  # Type-tree-value
16703     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:2")  # Type-tree-right
16704 $test-function-header-with-multiple-args-and-outputs:out1:
16705     # outputs = lookup(outputs->next)
16706     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
16707     89/<- %edx 0/r32/eax
16708     # v = lookup(inouts->value)
16709     (lookup *edx *(edx+4))  # List-value List-value => eax
16710     89/<- %ebx 0/r32/eax
16711     # check v->name
16712     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
16713     (check-strings-equal %eax "_" "F - test-function-header-with-multiple-args-and-outputs/output:1")
16714     # check v->register
16715     (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
16716     (check-strings-equal %eax "edx" "F - test-function-header-with-multiple-args-and-outputs/output:1/register")
16717     # check v->type
16718     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
16719     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:0")  # Type-tree-is-atom
16720     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:1")  # Type-tree-value
16721     (check-ints-equal *(eax+0c) 0 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:2")  # Type-tree-right
16722     # . epilogue
16723     89/<- %esp 5/r32/ebp
16724     5d/pop-to-ebp
16725     c3/return
16726 
16727 # format for variables with types
16728 #   x: int
16729 #   x: int,
16730 #   x/eax: int
16731 #   x/eax: int,
16732 # ignores at most one trailing comma
16733 # WARNING: modifies name
16734 parse-var-with-type:  # name: (addr slice), first-line: (addr stream byte), out: (addr handle var), fn-name: (addr array byte), err: (addr buffered-file), ed: (addr exit-descriptor)
16735     # pseudocode:
16736     #   var s: slice
16737     #   if (!slice-ends-with(name, ":"))
16738     #     abort
16739     #   --name->end to skip ':'
16740     #   next-token-from-slice(name->start, name->end, '/', s)
16741     #   new-var-from-slice(s, out)
16742     #   ## register
16743     #   next-token-from-slice(s->end, name->end, '/', s)
16744     #   if (!slice-empty?(s))
16745     #     out->register = slice-to-string(s)
16746     #   ## type
16747     #   var type: (handle type-tree) = parse-type(first-line)
16748     #   out->type = type
16749     #
16750     # . prologue
16751     55/push-ebp
16752     89/<- %ebp 4/r32/esp
16753     # . save registers
16754     50/push-eax
16755     51/push-ecx
16756     52/push-edx
16757     53/push-ebx
16758     56/push-esi
16759     57/push-edi
16760     # esi = name
16761     8b/-> *(ebp+8) 6/r32/esi
16762     # if (!slice-ends-with?(name, ":")) abort
16763     8b/-> *(esi+4) 1/r32/ecx  # Slice-end
16764     49/decrement-ecx
16765     8a/copy-byte *ecx 1/r32/CL
16766     81 4/subop/and %ecx 0xff/imm32
16767     81 7/subop/compare %ecx 0x3a/imm32/colon
16768     0f 85/jump-if-!= $parse-var-with-type:abort/disp32
16769     # --name->end to skip ':'
16770     ff 1/subop/decrement *(esi+4)
16771     # var s/ecx: slice
16772     68/push 0/imm32/end
16773     68/push 0/imm32/start
16774     89/<- %ecx 4/r32/esp
16775 $parse-var-with-type:parse-name:
16776     (next-token-from-slice *esi *(esi+4) 0x2f %ecx)  # Slice-start, Slice-end, '/'
16777 $parse-var-with-type:create-var:
16778     # new-var-from-slice(s, out)
16779     (new-var-from-slice Heap %ecx *(ebp+0x10))
16780     # save out->register
16781 $parse-var-with-type:save-register:
16782     # . var out-addr/edi: (addr var) = lookup(*out)
16783     8b/-> *(ebp+0x10) 7/r32/edi
16784     (lookup *edi *(edi+4))  # => eax
16785     89/<- %edi 0/r32/eax
16786     # . s = next-token(...)
16787     (next-token-from-slice *(ecx+4) *(esi+4) 0x2f %ecx)  # s->end, name->end, '/'
16788     # . if (!slice-empty?(s)) out->register = slice-to-string(s)
16789     {
16790 $parse-var-with-type:write-register:
16791       (slice-empty? %ecx)  # => eax
16792       3d/compare-eax-and 0/imm32/false
16793       75/jump-if-!= break/disp8
16794       # out->register = slice-to-string(s)
16795       8d/copy-address *(edi+0x18) 0/r32/eax  # Var-register
16796       (slice-to-string Heap %ecx %eax)
16797     }
16798 $parse-var-with-type:save-type:
16799     8d/copy-address *(edi+8) 0/r32/eax  # Var-type
16800     (parse-type Heap *(ebp+0xc) %eax *(ebp+0x18) *(ebp+0x1c))
16801 $parse-var-with-type:check-register:
16802     (lookup *(edi+0x18) *(edi+0x1c))  # Var-register Var-register => eax
16803     3d/compare-eax-and 0/imm32
16804     74/jump-if-= $parse-var-with-type:end/disp8
16805     (is-float-register? %eax)  # => eax
16806     {
16807       3d/compare-eax-and 0/imm32/false
16808       74/jump-if-= break/disp8
16809       # var is in a float register; ensure type is float
16810       (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
16811       (is-simple-mu-type? %eax 0xf)  # float => eax
16812       3d/compare-eax-and 0/imm32/false
16813       0f 84/jump-if-= $parse-var-with-type:error-non-float-in-floating-point-register/disp32
16814       eb/jump $parse-var-with-type:end/disp8
16815     }
16816     # var is not in a float register; ensure type is not float
16817     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
16818     (is-simple-mu-type? %eax 0xf)  # float => eax
16819     3d/compare-eax-and 0/imm32/false
16820     0f 85/jump-if-!= $parse-var-with-type:error-float-in-integer-register/disp32
16821 $parse-var-with-type:end:
16822     # . reclaim locals
16823     81 0/subop/add %esp 8/imm32
16824     # . restore registers
16825     5f/pop-to-edi
16826     5e/pop-to-esi
16827     5b/pop-to-ebx
16828     5a/pop-to-edx
16829     59/pop-to-ecx
16830     58/pop-to-eax
16831     # . epilogue
16832     89/<- %esp 5/r32/ebp
16833     5d/pop-to-ebp
16834     c3/return
16835 
16836 $parse-var-with-type:abort:
16837     # error("fn " fn ": var should have form 'name: type' in '" line "'\n")
16838     (write-buffered *(ebp+0x18) "fn ")
16839     (write-buffered *(ebp+0x18) *(ebp+0x14))
16840     (write-buffered *(ebp+0x18) ": var should have form 'name: type' in '")
16841     (flush *(ebp+0x18))
16842     (rewind-stream *(ebp+0xc))
16843     (write-stream-data *(ebp+0x18) *(ebp+0xc))
16844     (write-buffered *(ebp+0x18) "'\n")
16845     (flush *(ebp+0x18))
16846     (stop *(ebp+0x1c) 1)
16847     # never gets here
16848 
16849 $parse-var-with-type:error-float-in-integer-register:
16850     # error("fn " fn ": float var '" var "' should be in a floating-point register\n")
16851     (write-buffered *(ebp+0x18) "fn ")
16852     (write-buffered *(ebp+0x18) *(ebp+0x14))
16853     (write-buffered *(ebp+0x18) ": float var '")
16854     (lookup *edi *(edi+4))  # Var-name Var-name => eax
16855     (write-buffered *(ebp+0x18) %eax)
16856     (write-buffered *(ebp+0x18) "' should be in a floating-point register\n")
16857     (flush *(ebp+0x18))
16858     (stop *(ebp+0x1c) 1)
16859     # never gets here
16860 
16861 $parse-var-with-type:error-non-float-in-floating-point-register:
16862     # error("fn " fn ": non-float var '" var "' should be in an integer register\n")
16863     (write-buffered *(ebp+0x18) "fn ")
16864     (write-buffered *(ebp+0x18) *(ebp+0x14))
16865     (write-buffered *(ebp+0x18) ": non-float var '")
16866     (lookup *edi *(edi+4))  # Var-name Var-name => eax
16867     (write-buffered *(ebp+0x18) %eax)
16868     (write-buffered *(ebp+0x18) "' should be in an integer register\n")
16869     (flush *(ebp+0x18))
16870     (stop *(ebp+0x1c) 1)
16871     # never gets here
16872 
16873 is-float-register?:  # r: (addr array byte) -> result/eax: boolean
16874     # . prologue
16875     55/push-ebp
16876     89/<- %ebp 4/r32/esp
16877     #
16878     (get Mu-registers-unique *(ebp+8) 0xc "Mu-registers-unique")  # => eax
16879     81 7/subop/compare *eax 8/imm32/start-of-floating-point-registers
16880     0f 9d/set-if->= %al
16881     81 4/subop/and %eax 0xff/imm32
16882 $is-float-register?:end:
16883     # . epilogue
16884     89/<- %esp 5/r32/ebp
16885     5d/pop-to-ebp
16886     c3/return
16887 
16888 parse-type:  # ad: (addr allocation-descriptor), in: (addr stream byte), out: (addr handle type-tree), err: (addr buffered-file), ed: (addr exit-descriptor)
16889     # pseudocode:
16890     #   var s: slice = next-mu-token(in)
16891     #   assert s != ""
16892     #   assert s != "->"
16893     #   assert s != "{"
16894     #   assert s != "}"
16895     #   if s == ")"
16896     #     return
16897     #   out = allocate(Type-tree)
16898     #   if s != "("
16899     #     HACK: if s is an int, parse and return it
16900     #     out->is-atom? = true
16901     #     if (s[0] == "_")
16902     #       out->value = type-parameter
16903     #       out->parameter-name = slice-to-string(ad, s)
16904     #     else
16905     #       out->value = pos-or-insert-slice(Type-id, s)
16906     #     return
16907     #   out->left = parse-type(ad, in)
16908     #   out->right = parse-type-tree(ad, in)
16909     #
16910     # . prologue
16911     55/push-ebp
16912     89/<- %ebp 4/r32/esp
16913     # . save registers
16914     50/push-eax
16915     51/push-ecx
16916     52/push-edx
16917     # clear out
16918     (zero-out *(ebp+0x10) *Handle-size)
16919     # var s/ecx: slice
16920     68/push 0/imm32
16921     68/push 0/imm32
16922     89/<- %ecx 4/r32/esp
16923     # s = next-mu-token(in)
16924     (next-mu-token *(ebp+0xc) %ecx)
16925 #?     (write-buffered Stderr "tok: ")
16926 #?     (write-slice-buffered Stderr %ecx)
16927 #?     (write-buffered Stderr "$\n")
16928 #?     (flush Stderr)
16929     # assert s != ""
16930     (slice-equal? %ecx "")  # => eax
16931     3d/compare-eax-and 0/imm32/false
16932     0f 85/jump-if-!= $parse-type:abort/disp32
16933     # assert s != "{"
16934     (slice-equal? %ecx "{")  # => eax
16935     3d/compare-eax-and 0/imm32/false
16936     0f 85/jump-if-!= $parse-type:abort/disp32
16937     # assert s != "}"
16938     (slice-equal? %ecx "}")  # => eax
16939     3d/compare-eax-and 0/imm32/false
16940     0f 85/jump-if-!= $parse-type:abort/disp32
16941     # assert s != "->"
16942     (slice-equal? %ecx "->")  # => eax
16943     3d/compare-eax-and 0/imm32/false
16944     0f 85/jump-if-!= $parse-type:abort/disp32
16945     # if (s == ")") return
16946     (slice-equal? %ecx ")")  # => eax
16947     3d/compare-eax-and 0/imm32/false
16948     0f 85/jump-if-!= $parse-type:end/disp32
16949     # out = new tree
16950     (allocate *(ebp+8) *Type-tree-size *(ebp+0x10))
16951     # var out-addr/edx: (addr type-tree) = lookup(*out)
16952     8b/-> *(ebp+0x10) 2/r32/edx
16953     (lookup *edx *(edx+4))  # => eax
16954     89/<- %edx 0/r32/eax
16955     {
16956       # if (s != "(") break
16957       (slice-equal? %ecx "(")  # => eax
16958       3d/compare-eax-and 0/imm32/false
16959       0f 85/jump-if-!= break/disp32
16960       # if s is a number, store it in the type's size field
16961       {
16962 $parse-type:check-for-int:
16963         # var tmp/eax: byte = *s->slice
16964         8b/-> *ecx 0/r32/eax
16965         8a/copy-byte *eax 0/r32/AL
16966         81 4/subop/and %eax 0xff/imm32
16967         # TODO: raise an error on `var x: (array int a)`
16968         (is-decimal-digit? %eax)  # => eax
16969         3d/compare-eax-and 0/imm32/false
16970         74/jump-if-= break/disp8
16971         #
16972         (is-hex-int? %ecx)  # => eax
16973         3d/compare-eax-and 0/imm32/false
16974         74/jump-if-= break/disp8
16975 $parse-type:int:
16976         (check-mu-hex-int %ecx *(ebp+0x14) *(ebp+0x18))
16977         (parse-hex-int-from-slice %ecx)  # => eax
16978         c7 0/subop/copy *(edx+4) 9/imm32/type-id-array-capacity  # Type-tree-value
16979         89/<- *(edx+8) 0/r32/eax  # Type-tree-value-size
16980         e9/jump $parse-type:end/disp32
16981       }
16982 $parse-type:atom:
16983       # out->is-atom? = true
16984       c7 0/subop/copy *edx 1/imm32/true  # Type-tree-is-atom
16985       {
16986 $parse-type:check-for-type-parameter:
16987         # var tmp/eax: byte = *s->slice
16988         8b/-> *ecx 0/r32/eax
16989         8a/copy-byte *eax 0/r32/AL
16990         81 4/subop/and %eax 0xff/imm32
16991         # if (tmp != '_') break
16992         3d/compare-eax-and 0x5f/imm32/_
16993         75/jump-if-!= break/disp8
16994 $parse-type:type-parameter:
16995         # out->value = type-parameter
16996         c7 0/subop/copy *(edx+4) 0xa/imm32/type-parameter  # Type-tree-value
16997         # out->parameter-name = slice-to-string(ad, s)
16998         8d/copy-address *(edx+8) 0/r32/eax  # Type-tree-parameter-name
16999         (slice-to-string *(ebp+8) %ecx %eax)
17000         e9/jump $parse-type:end/disp32
17001       }
17002 $parse-type:non-type-parameter:
17003       # out->value = pos-or-insert-slice(Type-id, s)
17004       (pos-or-insert-slice Type-id %ecx)  # => eax
17005       89/<- *(edx+4) 0/r32/eax  # Type-tree-value
17006       e9/jump $parse-type:end/disp32
17007     }
17008 $parse-type:non-atom:
17009     # otherwise s == "("
17010     # out->left = parse-type(ad, in)
17011     8d/copy-address *(edx+4) 0/r32/eax  # Type-tree-left
17012     (parse-type *(ebp+8) *(ebp+0xc) %eax *(ebp+0x14) *(ebp+0x18))
17013     # out->right = parse-type-tree(ad, in)
17014     8d/copy-address *(edx+0xc) 0/r32/eax  # Type-tree-right
17015     (parse-type-tree *(ebp+8) *(ebp+0xc) %eax *(ebp+0x14) *(ebp+0x18))
17016 $parse-type:end:
17017     # . reclaim locals
17018     81 0/subop/add %esp 8/imm32
17019     # . restore registers
17020     5a/pop-to-edx
17021     59/pop-to-ecx
17022     58/pop-to-eax
17023     # . epilogue
17024     89/<- %esp 5/r32/ebp
17025     5d/pop-to-ebp
17026     c3/return
17027 
17028 $parse-type:abort:
17029     # error("unexpected token when parsing type: '" s "'\n")
17030     (write-buffered *(ebp+0x14) "unexpected token when parsing type: '")
17031     (write-slice-buffered *(ebp+0x14) %ecx)
17032     (write-buffered *(ebp+0x14) "'\n")
17033     (flush *(ebp+0x14))
17034     (stop *(ebp+0x18) 1)
17035     # never gets here
17036 
17037 parse-type-tree:  # ad: (addr allocation-descriptor), in: (addr stream byte), out: (addr handle type-tree), err: (addr buffered-file), ed: (addr exit-descriptor)
17038     # pseudocode:
17039     #   var tmp: (handle type-tree) = parse-type(ad, in)
17040     #   if tmp == 0
17041     #     return 0
17042     #   out = allocate(Type-tree)
17043     #   out->left = tmp
17044     #   out->right = parse-type-tree(ad, in)
17045     #
17046     # . prologue
17047     55/push-ebp
17048     89/<- %ebp 4/r32/esp
17049     # . save registers
17050     50/push-eax
17051     51/push-ecx
17052     52/push-edx
17053     #
17054     (zero-out *(ebp+0x10) *Handle-size)
17055     # var tmp/ecx: (handle type-tree)
17056     68/push 0/imm32
17057     68/push 0/imm32
17058     89/<- %ecx 4/r32/esp
17059     # tmp = parse-type(ad, in)
17060     (parse-type *(ebp+8) *(ebp+0xc) %ecx *(ebp+0x14) *(ebp+0x18))
17061     # if (tmp == 0) return
17062     81 7/subop/compare *ecx 0/imm32
17063     74/jump-if-= $parse-type-tree:end/disp8
17064     # out = new tree
17065     (allocate *(ebp+8) *Type-tree-size *(ebp+0x10))
17066     # var out-addr/edx: (addr tree) = lookup(*out)
17067     8b/-> *(ebp+0x10) 2/r32/edx
17068     (lookup *edx *(edx+4))  # => eax
17069     89/<- %edx 0/r32/eax
17070     # out->left = tmp
17071     8b/-> *ecx 0/r32/eax
17072     89/<- *(edx+4) 0/r32/eax  # Type-tree-left
17073     8b/-> *(ecx+4) 0/r32/eax
17074     89/<- *(edx+8) 0/r32/eax  # Type-tree-left
17075     # out->right = parse-type-tree(ad, in)
17076     8d/copy-address *(edx+0xc) 0/r32/eax  # Type-tree-right
17077     (parse-type-tree *(ebp+8) *(ebp+0xc) %eax *(ebp+0x14) *(ebp+0x18))
17078 $parse-type-tree:end:
17079     # . reclaim locals
17080     81 0/subop/add %esp 8/imm32
17081     # . restore registers
17082     5a/pop-to-edx
17083     59/pop-to-ecx
17084     58/pop-to-eax
17085     # . epilogue
17086     89/<- %esp 5/r32/ebp
17087     5d/pop-to-ebp
17088     c3/return
17089 
17090 next-mu-token:  # in: (addr stream byte), out: (addr slice)
17091     # pseudocode:
17092     # start:
17093     #   skip-chars-matching-whitespace(in)
17094     #   if in->read >= in->write              # end of in
17095     #     out = {0, 0}
17096     #     return
17097     #   out->start = &in->data[in->read]
17098     #   var curr-byte/eax: byte = in->data[in->read]
17099     #   if curr->byte == ','                  # comment token
17100     #     ++in->read
17101     #     goto start
17102     #   if curr-byte == '#'                   # comment
17103     #     goto done                             # treat as eof
17104     #   if curr-byte == '"'                   # string literal
17105     #     skip-string(in)
17106     #     goto done                           # no metadata
17107     #   if curr-byte == '('
17108     #     ++in->read
17109     #     goto done
17110     #   if curr-byte == ')'
17111     #     ++in->read
17112     #     goto done
17113     #   # read a word
17114     #   while true
17115     #     if in->read >= in->write
17116     #       break
17117     #     curr-byte = in->data[in->read]
17118     #     if curr-byte == ' '
17119     #       break
17120     #     if curr-byte == '\r'
17121     #       break
17122     #     if curr-byte == '\n'
17123     #       break
17124     #     if curr-byte == '('
17125     #       break
17126     #     if curr-byte == ')'
17127     #       break
17128     #     if curr-byte == ','
17129     #       break
17130     #     ++in->read
17131     # done:
17132     #   out->end = &in->data[in->read]
17133     #
17134     # . prologue
17135     55/push-ebp
17136     89/<- %ebp 4/r32/esp
17137     # . save registers
17138     50/push-eax
17139     51/push-ecx
17140     56/push-esi
17141     57/push-edi
17142     # esi = in
17143     8b/-> *(ebp+8) 6/r32/esi
17144     # edi = out
17145     8b/-> *(ebp+0xc) 7/r32/edi
17146 $next-mu-token:start:
17147     (skip-chars-matching-whitespace %esi)
17148 $next-mu-token:check0:
17149     # if (in->read >= in->write) return out = {0, 0}
17150     # . ecx = in->read
17151     8b/-> *(esi+4) 1/r32/ecx
17152     # . if (ecx >= in->write) return out = {0, 0}
17153     3b/compare<- *esi 1/r32/ecx
17154     c7 0/subop/copy *edi 0/imm32
17155     c7 0/subop/copy *(edi+4) 0/imm32
17156     0f 8d/jump-if->= $next-mu-token:end/disp32
17157     # out->start = &in->data[in->read]
17158     8d/copy-address *(esi+ecx+0xc) 0/r32/eax
17159     89/<- *edi 0/r32/eax
17160     # var curr-byte/eax: byte = in->data[in->read]
17161     31/xor-with %eax 0/r32/eax
17162     8a/copy-byte *(esi+ecx+0xc) 0/r32/AL
17163     {
17164 $next-mu-token:check-for-comma:
17165       # if (curr-byte != ',') break
17166       3d/compare-eax-and 0x2c/imm32/comma
17167       75/jump-if-!= break/disp8
17168       # ++in->read
17169       ff 0/subop/increment *(esi+4)
17170       # restart
17171       e9/jump $next-mu-token:start/disp32
17172     }
17173     {
17174 $next-mu-token:check-for-comment:
17175       # if (curr-byte != '#') break
17176       3d/compare-eax-and 0x23/imm32/pound
17177       75/jump-if-!= break/disp8
17178       # return eof
17179       e9/jump $next-mu-token:done/disp32
17180     }
17181     {
17182 $next-mu-token:check-for-string-literal:
17183       # if (curr-byte != '"') break
17184       3d/compare-eax-and 0x22/imm32/dquote
17185       75/jump-if-!= break/disp8
17186       (skip-string %esi)
17187       # return
17188       e9/jump $next-mu-token:done/disp32
17189     }
17190     {
17191 $next-mu-token:check-for-open-paren:
17192       # if (curr-byte != '(') break
17193       3d/compare-eax-and 0x28/imm32/open-paren
17194       75/jump-if-!= break/disp8
17195       # ++in->read
17196       ff 0/subop/increment *(esi+4)
17197       # return
17198       e9/jump $next-mu-token:done/disp32
17199     }
17200     {
17201 $next-mu-token:check-for-close-paren:
17202       # if (curr-byte != ')') break
17203       3d/compare-eax-and 0x29/imm32/close-paren
17204       75/jump-if-!= break/disp8
17205       # ++in->read
17206       ff 0/subop/increment *(esi+4)
17207       # return
17208       e9/jump $next-mu-token:done/disp32
17209     }
17210     {
17211 $next-mu-token:regular-word-without-metadata:
17212       # if (in->read >= in->write) break
17213       # . ecx = in->read
17214       8b/-> *(esi+4) 1/r32/ecx
17215       # . if (ecx >= in->write) break
17216       3b/compare<- *esi 1/r32/ecx
17217       7d/jump-if->= break/disp8
17218       # var c/eax: byte = in->data[in->read]
17219       31/xor-with %eax 0/r32/eax
17220       8a/copy-byte *(esi+ecx+0xc) 0/r32/AL
17221       # if (c == ' ') break
17222       3d/compare-eax-and 0x20/imm32/space
17223       74/jump-if-= break/disp8
17224       # if (c == '\r') break
17225       3d/compare-eax-and 0xd/imm32/carriage-return
17226       74/jump-if-= break/disp8
17227       # if (c == '\n') break
17228       3d/compare-eax-and 0xa/imm32/newline
17229       74/jump-if-= break/disp8
17230       # if (c == '(') break
17231       3d/compare-eax-and 0x28/imm32/open-paren
17232       0f 84/jump-if-= break/disp32
17233       # if (c == ')') break
17234       3d/compare-eax-and 0x29/imm32/close-paren
17235       0f 84/jump-if-= break/disp32
17236       # if (c == ',') break
17237       3d/compare-eax-and 0x2c/imm32/comma
17238       0f 84/jump-if-= break/disp32
17239       # ++in->read
17240       ff 0/subop/increment *(esi+4)
17241       #
17242       e9/jump loop/disp32
17243     }
17244 $next-mu-token:done:
17245     # out->end = &in->data[in->read]
17246     8b/-> *(esi+4) 1/r32/ecx
17247     8d/copy-address *(esi+ecx+0xc) 0/r32/eax
17248     89/<- *(edi+4) 0/r32/eax
17249 $next-mu-token:end:
17250     # . restore registers
17251     5f/pop-to-edi
17252     5e/pop-to-esi
17253     59/pop-to-ecx
17254     58/pop-to-eax
17255     # . epilogue
17256     89/<- %esp 5/r32/ebp
17257     5d/pop-to-ebp
17258     c3/return
17259 
17260 pos-or-insert-slice:  # arr: (addr stream (addr array byte)), s: (addr slice) -> index/eax: int
17261     # . prologue
17262     55/push-ebp
17263     89/<- %ebp 4/r32/esp
17264     # if (pos-slice(arr, s) != -1) return it
17265     (pos-slice *(ebp+8) *(ebp+0xc))  # => eax
17266     3d/compare-eax-and -1/imm32
17267     75/jump-if-!= $pos-or-insert-slice:end/disp8
17268 $pos-or-insert-slice:insert:
17269     # var s2/eax: (handle array byte)
17270     68/push 0/imm32
17271     68/push 0/imm32
17272     89/<- %eax 4/r32/esp
17273     (slice-to-string Heap *(ebp+0xc) %eax)
17274     # throw away alloc-id
17275     (lookup *eax *(eax+4))  # => eax
17276     (write-int *(ebp+8) %eax)
17277     (pos-slice *(ebp+8) *(ebp+0xc))  # => eax
17278 $pos-or-insert-slice:end:
17279     # . reclaim locals
17280     81 0/subop/add %esp 8/imm32
17281     # . epilogue
17282     89/<- %esp 5/r32/ebp
17283     5d/pop-to-ebp
17284     c3/return
17285 
17286 # return the index in an array of strings matching 's', -1 if not found
17287 # index is denominated in elements, not bytes
17288 pos-slice:  # arr: (addr stream (addr array byte)), s: (addr slice) -> index/eax: int
17289     # . prologue
17290     55/push-ebp
17291     89/<- %ebp 4/r32/esp
17292     # . save registers
17293     51/push-ecx
17294     52/push-edx
17295     53/push-ebx
17296     56/push-esi
17297 #?     (write-buffered Stderr "pos-slice: ")
17298 #?     (write-slice-buffered Stderr *(ebp+0xc))
17299 #?     (write-buffered Stderr "\n")
17300 #?     (flush Stderr)
17301     # esi = arr
17302     8b/-> *(ebp+8) 6/r32/esi
17303     # var index/ecx: int = 0
17304     b9/copy-to-ecx 0/imm32
17305     # var curr/edx: (addr (addr array byte)) = arr->data
17306     8d/copy-address *(esi+0xc) 2/r32/edx
17307     # var max/ebx: (addr (addr array byte)) = &arr->data[arr->write]
17308     8b/-> *esi 3/r32/ebx
17309     8d/copy-address *(esi+ebx+0xc) 3/r32/ebx
17310     {
17311 #?       (write-buffered Stderr "  ")
17312 #?       (write-int32-hex-buffered Stderr %ecx)
17313 #?       (write-buffered Stderr "\n")
17314 #?       (flush Stderr)
17315       # if (curr >= max) return -1
17316       39/compare %edx 3/r32/ebx
17317       b8/copy-to-eax -1/imm32
17318       73/jump-if-addr>= $pos-slice:end/disp8
17319       # if (slice-equal?(s, *curr)) break
17320       (slice-equal? *(ebp+0xc) *edx)  # => eax
17321       3d/compare-eax-and 0/imm32/false
17322       75/jump-if-!= break/disp8
17323       # ++index
17324       41/increment-ecx
17325       # curr += 4
17326       81 0/subop/add %edx 4/imm32
17327       #
17328       eb/jump loop/disp8
17329     }
17330     # return index
17331     89/<- %eax 1/r32/ecx
17332 $pos-slice:end:
17333 #?     (write-buffered Stderr "=> ")
17334 #?     (write-int32-hex-buffered Stderr %eax)
17335 #?     (write-buffered Stderr "\n")
17336     # . restore registers
17337     5e/pop-to-esi
17338     5b/pop-to-ebx
17339     5a/pop-to-edx
17340     59/pop-to-ecx
17341     # . epilogue
17342     89/<- %esp 5/r32/ebp
17343     5d/pop-to-ebp
17344     c3/return
17345 
17346 test-parse-var-with-type:
17347     # . prologue
17348     55/push-ebp
17349     89/<- %ebp 4/r32/esp
17350     # setup
17351     8b/-> *Primitive-type-ids 0/r32/eax
17352     89/<- *Type-id 0/r32/eax  # stream-write
17353     # (eax..ecx) = "x:"
17354     b8/copy-to-eax "x:"/imm32
17355     8b/-> *eax 1/r32/ecx
17356     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17357     05/add-to-eax 4/imm32
17358     # var slice/ecx: slice = {eax, ecx}
17359     51/push-ecx
17360     50/push-eax
17361     89/<- %ecx 4/r32/esp
17362     # _test-input-stream contains "int"
17363     (clear-stream _test-input-stream)
17364     (write _test-input-stream "int")
17365     # var v/edx: (handle var)
17366     68/push 0/imm32
17367     68/push 0/imm32
17368     89/<- %edx 4/r32/esp
17369     #
17370     (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0)
17371     # var v-addr/edx: (addr var) = lookup(v)
17372     (lookup *edx *(edx+4))  # => eax
17373     89/<- %edx 0/r32/eax
17374     # check v-addr->name
17375     (lookup *edx *(edx+4))  # Var-name Var-name => eax
17376     (check-strings-equal %eax "x" "F - test-parse-var-with-type/name")
17377     # check v-addr->type
17378     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
17379     (check-ints-equal *eax 1 "F - test-parse-var-with-type/type:0")  # Type-tree-is-atom
17380     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-type/type:1")  # Type-tree-value
17381     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-type/type:2")  # Type-tree-right
17382     # . epilogue
17383     89/<- %esp 5/r32/ebp
17384     5d/pop-to-ebp
17385     c3/return
17386 
17387 test-parse-var-with-type-and-register:
17388     # . prologue
17389     55/push-ebp
17390     89/<- %ebp 4/r32/esp
17391     # setup
17392     8b/-> *Primitive-type-ids 0/r32/eax
17393     89/<- *Type-id 0/r32/eax  # stream-write
17394     # (eax..ecx) = "x/eax:"
17395     b8/copy-to-eax "x/eax:"/imm32
17396     8b/-> *eax 1/r32/ecx
17397     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17398     05/add-to-eax 4/imm32
17399     # var slice/ecx: slice = {eax, ecx}
17400     51/push-ecx
17401     50/push-eax
17402     89/<- %ecx 4/r32/esp
17403     # _test-input-stream contains "int"
17404     (clear-stream _test-input-stream)
17405     (write _test-input-stream "int")
17406     # var v/edx: (handle var)
17407     68/push 0/imm32
17408     68/push 0/imm32
17409     89/<- %edx 4/r32/esp
17410     #
17411     (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0)
17412     # var v-addr/edx: (addr var) = lookup(v)
17413     (lookup *edx *(edx+4))  # => eax
17414     89/<- %edx 0/r32/eax
17415     # check v-addr->name
17416     (lookup *edx *(edx+4))  # Var-name Var-name => eax
17417     (check-strings-equal %eax "x" "F - test-parse-var-with-type-and-register/name")
17418     # check v-addr->register
17419     (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
17420     (check-strings-equal %eax "eax" "F - test-parse-var-with-type-and-register/register")
17421     # check v-addr->type
17422     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
17423     (check-ints-equal *eax 1 "F - test-parse-var-with-type-and-register/type:0")  # Type-tree-is-atom
17424     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-type-and-register/type:1")  # Type-tree-left
17425     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-type-and-register/type:2")  # Type-tree-right
17426     # . epilogue
17427     89/<- %esp 5/r32/ebp
17428     5d/pop-to-ebp
17429     c3/return
17430 
17431 test-parse-var-with-trailing-characters:
17432     # . prologue
17433     55/push-ebp
17434     89/<- %ebp 4/r32/esp
17435     # setup
17436     8b/-> *Primitive-type-ids 0/r32/eax
17437     89/<- *Type-id 0/r32/eax  # stream-write
17438     # (eax..ecx) = "x:"
17439     b8/copy-to-eax "x:"/imm32
17440     8b/-> *eax 1/r32/ecx
17441     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17442     05/add-to-eax 4/imm32
17443     # var slice/ecx: slice = {eax, ecx}
17444     51/push-ecx
17445     50/push-eax
17446     89/<- %ecx 4/r32/esp
17447     # _test-input-stream contains "int,"
17448     (clear-stream _test-input-stream)
17449     (write _test-input-stream "int,")
17450     # var v/edx: (handle var)
17451     68/push 0/imm32
17452     68/push 0/imm32
17453     89/<- %edx 4/r32/esp
17454     #
17455     (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0)
17456     # var v-addr/edx: (addr var) = lookup(v)
17457     (lookup *edx *(edx+4))  # => eax
17458     89/<- %edx 0/r32/eax
17459     # check v-addr->name
17460     (lookup *edx *(edx+4))  # Var-name Var-name => eax
17461     (check-strings-equal %eax "x" "F - test-parse-var-with-trailing-characters/name")
17462     # check v-addr->register
17463     (check-ints-equal *(edx+0x18) 0 "F - test-parse-var-with-trailing-characters/register")  # Var-register
17464     # check v-addr->type
17465     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
17466     (check-ints-equal *eax 1 "F - test-parse-var-with-trailing-characters/type:0")  # Type-tree-is-atom
17467     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-trailing-characters/type:1")  # Type-tree-left
17468     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-trailing-characters/type:1")  # Type-tree-right
17469     # . epilogue
17470     89/<- %esp 5/r32/ebp
17471     5d/pop-to-ebp
17472     c3/return
17473 
17474 test-parse-var-with-register-and-trailing-characters:
17475     # . prologue
17476     55/push-ebp
17477     89/<- %ebp 4/r32/esp
17478     # setup
17479     8b/-> *Primitive-type-ids 0/r32/eax
17480     89/<- *Type-id 0/r32/eax  # stream-write
17481     # (eax..ecx) = "x/eax:"
17482     b8/copy-to-eax "x/eax:"/imm32
17483     8b/-> *eax 1/r32/ecx
17484     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17485     05/add-to-eax 4/imm32
17486     # var slice/ecx: slice = {eax, ecx}
17487     51/push-ecx
17488     50/push-eax
17489     89/<- %ecx 4/r32/esp
17490     # _test-input-stream contains "int,"
17491     (clear-stream _test-input-stream)
17492     (write _test-input-stream "int,")
17493     # var v/edx: (handle var)
17494     68/push 0/imm32
17495     68/push 0/imm32
17496     89/<- %edx 4/r32/esp
17497     #
17498     (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0)
17499     # var v-addr/edx: (addr var) = lookup(v)
17500     (lookup *edx *(edx+4))  # => eax
17501     89/<- %edx 0/r32/eax
17502     # check v-addr->name
17503     (lookup *edx *(edx+4))  # Var-name Var-name => eax
17504     (check-strings-equal %eax "x" "F - test-parse-var-with-register-and-trailing-characters/name")
17505     # check v-addr->register
17506     (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
17507     (check-strings-equal %eax "eax" "F - test-parse-var-with-register-and-trailing-characters/register")
17508     # check v-addr->type
17509     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
17510     (check-ints-equal *eax 1 "F - test-parse-var-with-register-and-trailing-characters/type:0")  # Type-tree-is-atom
17511     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-register-and-trailing-characters/type:1")  # Type-tree-left
17512     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-register-and-trailing-characters/type:2")  # Type-tree-right
17513     # . epilogue
17514     89/<- %esp 5/r32/ebp
17515     5d/pop-to-ebp
17516     c3/return
17517 
17518 test-parse-var-with-compound-type:
17519     # . prologue
17520     55/push-ebp
17521     89/<- %ebp 4/r32/esp
17522     # setup
17523     8b/-> *Primitive-type-ids 0/r32/eax
17524     89/<- *Type-id 0/r32/eax  # stream-write
17525     # (eax..ecx) = "x:"
17526     b8/copy-to-eax "x:"/imm32
17527     8b/-> *eax 1/r32/ecx
17528     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17529     05/add-to-eax 4/imm32
17530     # var slice/ecx: slice = {eax, ecx}
17531     51/push-ecx
17532     50/push-eax
17533     89/<- %ecx 4/r32/esp
17534     # _test-input-stream contains "(addr int)"
17535     (clear-stream _test-input-stream)
17536     (write _test-input-stream "(addr int)")
17537     # var v/edx: (handle var)
17538     68/push 0/imm32
17539     68/push 0/imm32
17540     89/<- %edx 4/r32/esp
17541     #
17542     (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0)
17543     # var v-addr/edx: (addr var) = lookup(v)
17544     (lookup *edx *(edx+4))  # => eax
17545     89/<- %edx 0/r32/eax
17546     # check v-addr->name
17547     (lookup *edx *(edx+4))  # Var-name Var-name => eax
17548     (check-strings-equal %eax "x" "F - test-parse-var-with-compound-type/name")
17549     # check v-addr->register
17550     (check-ints-equal *(edx+0x18) 0 "F - test-parse-var-with-compound-type/register")  # Var-register
17551     # - check v-addr->type
17552     # var type/edx: (addr type-tree) = var->type
17553     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
17554     89/<- %edx 0/r32/eax
17555     # type is a non-atom
17556     (check-ints-equal *edx 0 "F - test-parse-var-with-compound-type/type:0")  # Type-tree-is-atom
17557     # type->left == atom(addr)
17558     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
17559     (check-ints-equal *eax 1 "F - test-parse-var-with-compound-type/type:1")  # Type-tree-is-atom
17560     (check-ints-equal *(eax+4) 2 "F - test-parse-var-with-compound-type/type:2")  # Type-tree-value
17561     # type->right->left == atom(int)
17562     (lookup *(edx+0xc) *(edx+0x10))  # Type-tree-right Type-tree-right => eax
17563     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
17564     (check-ints-equal *eax 1 "F - test-parse-var-with-compound-type/type:3")  # Type-tree-is-atom
17565     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-compound-type/type:4")  # Type-tree-value
17566     # type->right->right == null
17567     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-compound-type/type:5")  # Type-tree-right
17568     # . epilogue
17569     89/<- %esp 5/r32/ebp
17570     5d/pop-to-ebp
17571     c3/return
17572 
17573 # identifier starts with a letter or '$' or '_'
17574 # no constraints at the moment on later letters
17575 # all we really want to do so far is exclude '{', '}' and '->'
17576 is-identifier?:  # in: (addr slice) -> result/eax: boolean
17577     # . prologue
17578     55/push-ebp
17579     89/<- %ebp 4/r32/esp
17580     # if (slice-empty?(in)) return false
17581     (slice-empty? *(ebp+8))  # => eax
17582     3d/compare-eax-and 0/imm32/false
17583     75/jump-if-!= $is-identifier?:false/disp8
17584     # var c/eax: byte = *in->start
17585     8b/-> *(ebp+8) 0/r32/eax
17586     8b/-> *eax 0/r32/eax
17587     8a/copy-byte *eax 0/r32/AL
17588     81 4/subop/and %eax 0xff/imm32
17589     # if (c == '$') return true
17590     3d/compare-eax-and 0x24/imm32/$
17591     74/jump-if-= $is-identifier?:true/disp8
17592     # if (c == '_') return true
17593     3d/compare-eax-and 0x5f/imm32/_
17594     74/jump-if-= $is-identifier?:true/disp8
17595     # drop case
17596     25/and-eax-with 0x5f/imm32
17597     # if (c < 'A') return false
17598     3d/compare-eax-and 0x41/imm32/A
17599     7c/jump-if-< $is-identifier?:false/disp8
17600     # if (c > 'Z') return false
17601     3d/compare-eax-and 0x5a/imm32/Z
17602     7f/jump-if-> $is-identifier?:false/disp8
17603     # otherwise return true
17604 $is-identifier?:true:
17605     b8/copy-to-eax 1/imm32/true
17606     eb/jump $is-identifier?:end/disp8
17607 $is-identifier?:false:
17608     b8/copy-to-eax 0/imm32/false
17609 $is-identifier?:end:
17610     # . epilogue
17611     89/<- %esp 5/r32/ebp
17612     5d/pop-to-ebp
17613     c3/return
17614 
17615 test-is-identifier-dollar:
17616     # . prologue
17617     55/push-ebp
17618     89/<- %ebp 4/r32/esp
17619     # (eax..ecx) = "$a"
17620     b8/copy-to-eax "$a"/imm32
17621     8b/-> *eax 1/r32/ecx
17622     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17623     05/add-to-eax 4/imm32
17624     # var slice/ecx: slice = {eax, ecx}
17625     51/push-ecx
17626     50/push-eax
17627     89/<- %ecx 4/r32/esp
17628     #
17629     (is-identifier? %ecx)
17630     (check-ints-equal %eax 1 "F - test-is-identifier-dollar")
17631     # . epilogue
17632     89/<- %esp 5/r32/ebp
17633     5d/pop-to-ebp
17634     c3/return
17635 
17636 test-is-identifier-underscore:
17637     # . prologue
17638     55/push-ebp
17639     89/<- %ebp 4/r32/esp
17640     # (eax..ecx) = "_a"
17641     b8/copy-to-eax "_a"/imm32
17642     8b/-> *eax 1/r32/ecx
17643     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17644     05/add-to-eax 4/imm32
17645     # var slice/ecx: slice = {eax, ecx}
17646     51/push-ecx
17647     50/push-eax
17648     89/<- %ecx 4/r32/esp
17649     #
17650     (is-identifier? %ecx)
17651     (check-ints-equal %eax 1 "F - test-is-identifier-underscore")
17652     # . epilogue
17653     89/<- %esp 5/r32/ebp
17654     5d/pop-to-ebp
17655     c3/return
17656 
17657 test-is-identifier-a:
17658     # . prologue
17659     55/push-ebp
17660     89/<- %ebp 4/r32/esp
17661     # (eax..ecx) = "a$"
17662     b8/copy-to-eax "a$"/imm32
17663     8b/-> *eax 1/r32/ecx
17664     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17665     05/add-to-eax 4/imm32
17666     # var slice/ecx: slice = {eax, ecx}
17667     51/push-ecx
17668     50/push-eax
17669     89/<- %ecx 4/r32/esp
17670     #
17671     (is-identifier? %ecx)
17672     (check-ints-equal %eax 1 "F - test-is-identifier-a")
17673     # . epilogue
17674     89/<- %esp 5/r32/ebp
17675     5d/pop-to-ebp
17676     c3/return
17677 
17678 test-is-identifier-z:
17679     # . prologue
17680     55/push-ebp
17681     89/<- %ebp 4/r32/esp
17682     # (eax..ecx) = "z$"
17683     b8/copy-to-eax "z$"/imm32
17684     8b/-> *eax 1/r32/ecx
17685     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17686     05/add-to-eax 4/imm32
17687     # var slice/ecx: slice = {eax, ecx}
17688     51/push-ecx
17689     50/push-eax
17690     89/<- %ecx 4/r32/esp
17691     #
17692     (is-identifier? %ecx)
17693     (check-ints-equal %eax 1 "F - test-is-identifier-z")
17694     # . epilogue
17695     89/<- %esp 5/r32/ebp
17696     5d/pop-to-ebp
17697     c3/return
17698 
17699 test-is-identifier-A:
17700     # . prologue
17701     55/push-ebp
17702     89/<- %ebp 4/r32/esp
17703     # (eax..ecx) = "A$"
17704     b8/copy-to-eax "A$"/imm32
17705     8b/-> *eax 1/r32/ecx
17706     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17707     05/add-to-eax 4/imm32
17708     # var slice/ecx: slice = {eax, ecx}
17709     51/push-ecx
17710     50/push-eax
17711     89/<- %ecx 4/r32/esp
17712     #
17713     (is-identifier? %ecx)
17714     (check-ints-equal %eax 1 "F - test-is-identifier-A")
17715     # . epilogue
17716     89/<- %esp 5/r32/ebp
17717     5d/pop-to-ebp
17718     c3/return
17719 
17720 test-is-identifier-Z:
17721     # . prologue
17722     55/push-ebp
17723     89/<- %ebp 4/r32/esp
17724     # (eax..ecx) = "Z$"
17725     b8/copy-to-eax "Z$"/imm32
17726     8b/-> *eax 1/r32/ecx
17727     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17728     05/add-to-eax 4/imm32
17729     # var slice/ecx: slice = {eax, ecx}
17730     51/push-ecx
17731     50/push-eax
17732     89/<- %ecx 4/r32/esp
17733     #
17734     (is-identifier? %ecx)
17735     (check-ints-equal %eax 1 "F - test-is-identifier-Z")
17736     # . epilogue
17737     89/<- %esp 5/r32/ebp
17738     5d/pop-to-ebp
17739     c3/return
17740 
17741 test-is-identifier-at:
17742     # character before 'A' is invalid
17743     # . prologue
17744     55/push-ebp
17745     89/<- %ebp 4/r32/esp
17746     # (eax..ecx) = "@a"
17747     b8/copy-to-eax "@a"/imm32
17748     8b/-> *eax 1/r32/ecx
17749     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17750     05/add-to-eax 4/imm32
17751     # var slice/ecx: slice = {eax, ecx}
17752     51/push-ecx
17753     50/push-eax
17754     89/<- %ecx 4/r32/esp
17755     #
17756     (is-identifier? %ecx)
17757     (check-ints-equal %eax 0 "F - test-is-identifier-@")
17758     # . epilogue
17759     89/<- %esp 5/r32/ebp
17760     5d/pop-to-ebp
17761     c3/return
17762 
17763 test-is-identifier-square-bracket:
17764     # character after 'Z' is invalid
17765     # . prologue
17766     55/push-ebp
17767     89/<- %ebp 4/r32/esp
17768     # (eax..ecx) = "[a"
17769     b8/copy-to-eax "[a"/imm32
17770     8b/-> *eax 1/r32/ecx
17771     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17772     05/add-to-eax 4/imm32
17773     # var slice/ecx: slice = {eax, ecx}
17774     51/push-ecx
17775     50/push-eax
17776     89/<- %ecx 4/r32/esp
17777     #
17778     (is-identifier? %ecx)
17779     (check-ints-equal %eax 0 "F - test-is-identifier-@")
17780     # . epilogue
17781     89/<- %esp 5/r32/ebp
17782     5d/pop-to-ebp
17783     c3/return
17784 
17785 test-is-identifier-backtick:
17786     # character before 'a' is invalid
17787     # . prologue
17788     55/push-ebp
17789     89/<- %ebp 4/r32/esp
17790     # (eax..ecx) = "`a"
17791     b8/copy-to-eax "`a"/imm32
17792     8b/-> *eax 1/r32/ecx
17793     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17794     05/add-to-eax 4/imm32
17795     # var slice/ecx: slice = {eax, ecx}
17796     51/push-ecx
17797     50/push-eax
17798     89/<- %ecx 4/r32/esp
17799     #
17800     (is-identifier? %ecx)
17801     (check-ints-equal %eax 0 "F - test-is-identifier-backtick")
17802     # . epilogue
17803     89/<- %esp 5/r32/ebp
17804     5d/pop-to-ebp
17805     c3/return
17806 
17807 test-is-identifier-curly-brace-open:
17808     # character after 'z' is invalid; also used for blocks
17809     # . prologue
17810     55/push-ebp
17811     89/<- %ebp 4/r32/esp
17812     # (eax..ecx) = "{a"
17813     b8/copy-to-eax "{a"/imm32
17814     8b/-> *eax 1/r32/ecx
17815     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17816     05/add-to-eax 4/imm32
17817     # var slice/ecx: slice = {eax, ecx}
17818     51/push-ecx
17819     50/push-eax
17820     89/<- %ecx 4/r32/esp
17821     #
17822     (is-identifier? %ecx)
17823     (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-open")
17824     # . epilogue
17825     89/<- %esp 5/r32/ebp
17826     5d/pop-to-ebp
17827     c3/return
17828 
17829 test-is-identifier-curly-brace-close:
17830     # . prologue
17831     55/push-ebp
17832     89/<- %ebp 4/r32/esp
17833     # (eax..ecx) = "}a"
17834     b8/copy-to-eax "}a"/imm32
17835     8b/-> *eax 1/r32/ecx
17836     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17837     05/add-to-eax 4/imm32
17838     # var slice/ecx: slice = {eax, ecx}
17839     51/push-ecx
17840     50/push-eax
17841     89/<- %ecx 4/r32/esp
17842     #
17843     (is-identifier? %ecx)
17844     (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-close")
17845     # . epilogue
17846     89/<- %esp 5/r32/ebp
17847     5d/pop-to-ebp
17848     c3/return
17849 
17850 test-is-identifier-hyphen:
17851     # disallow leading '-' since '->' has special meaning
17852     # . prologue
17853     55/push-ebp
17854     89/<- %ebp 4/r32/esp
17855     # (eax..ecx) = "-a"
17856     b8/copy-to-eax "-a"/imm32
17857     8b/-> *eax 1/r32/ecx
17858     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17859     05/add-to-eax 4/imm32
17860     # var slice/ecx: slice = {eax, ecx}
17861     51/push-ecx
17862     50/push-eax
17863     89/<- %ecx 4/r32/esp
17864     #
17865     (is-identifier? %ecx)
17866     (check-ints-equal %eax 0 "F - test-is-identifier-hyphen")
17867     # . epilogue
17868     89/<- %esp 5/r32/ebp
17869     5d/pop-to-ebp
17870     c3/return
17871 
17872 populate-mu-function-body:  # in: (addr buffered-file), out: (addr function), vars: (addr stack live-var), err: (addr buffered-file), ed: (addr exit-descriptor)
17873     # . prologue
17874     55/push-ebp
17875     89/<- %ebp 4/r32/esp
17876     # . save registers
17877     50/push-eax
17878     56/push-esi
17879     57/push-edi
17880     # esi = in
17881     8b/-> *(ebp+8) 6/r32/esi
17882     # edi = out
17883     8b/-> *(ebp+0xc) 7/r32/edi
17884     # initialize some global state
17885     c7 0/subop/copy *Curr-block-depth 1/imm32
17886     # parse-mu-block(in, vars, out, out->body)
17887     8d/copy-address *(edi+0x18) 0/r32/eax  # Function-body
17888     (parse-mu-block %esi *(ebp+0x10) %edi %eax *(ebp+0x14) *(ebp+0x18))
17889 $populate-mu-function-body:end:
17890     # . restore registers
17891     5f/pop-to-edi
17892     5e/pop-to-esi
17893     58/pop-to-eax
17894     # . epilogue
17895     89/<- %esp 5/r32/ebp
17896     5d/pop-to-ebp
17897     c3/return
17898 
17899 # parses a block, assuming that the leading '{' has already been read by the caller
17900 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)
17901     # pseudocode:
17902     #   var line: (stream byte 512)
17903     #   var word-slice: slice
17904     #   allocate(Heap, Stmt-size, out)
17905     #   var out-addr: (addr block) = lookup(*out)
17906     #   out-addr->tag = 0/block
17907     #   out-addr->var = some unique name
17908     #   push(vars, {out-addr->var, false})
17909     #   while true                                  # line loop
17910     #     clear-stream(line)
17911     #     read-line-buffered(in, line)
17912     #     if (line->write == 0) break               # end of file
17913     #     word-slice = next-mu-token(line)
17914     #     if slice-empty?(word-slice)               # end of line
17915     #       continue
17916     #     else if slice-starts-with?(word-slice, "#")
17917     #       continue
17918     #     else if slice-equal?(word-slice, "{")
17919     #       assert(no-tokens-in(line))
17920     #       block = parse-mu-block(in, vars, fn)
17921     #       append-to-block(out-addr, block)
17922     #     else if slice-equal?(word-slice, "}")
17923     #       break
17924     #     else if slice-ends-with?(word-slice, ":")
17925     #       # TODO: error-check the rest of 'line'
17926     #       --word-slice->end to skip ':'
17927     #       named-block = parse-mu-named-block(word-slice, in, vars, fn)
17928     #       append-to-block(out-addr, named-block)
17929     #     else if slice-equal?(word-slice, "var")
17930     #       var-def = parse-mu-var-def(line, vars, fn)
17931     #       append-to-block(out-addr, var-def)
17932     #     else
17933     #       stmt = parse-mu-stmt(line, vars, fn)
17934     #       append-to-block(out-addr, stmt)
17935     #   pop(vars)
17936     #
17937     # . prologue
17938     55/push-ebp
17939     89/<- %ebp 4/r32/esp
17940     # . save registers
17941     50/push-eax
17942     51/push-ecx
17943     52/push-edx
17944     53/push-ebx
17945     57/push-edi
17946     # var line/ecx: (stream byte 512)
17947     81 5/subop/subtract %esp 0x200/imm32
17948     68/push 0x200/imm32/size
17949     68/push 0/imm32/read
17950     68/push 0/imm32/write
17951     89/<- %ecx 4/r32/esp
17952     # var word-slice/edx: slice
17953     68/push 0/imm32/end
17954     68/push 0/imm32/start
17955     89/<- %edx 4/r32/esp
17956     # allocate into out
17957     (allocate Heap *Stmt-size *(ebp+0x14))
17958     # var out-addr/edi: (addr block) = lookup(*out)
17959     8b/-> *(ebp+0x14) 7/r32/edi
17960     (lookup *edi *(edi+4))  # => eax
17961     89/<- %edi 0/r32/eax
17962     # out-addr->tag is 0 (block) by default
17963     # set out-addr->var
17964     8d/copy-address *(edi+0xc) 0/r32/eax  # Block-var
17965     (new-block-name *(ebp+0x10) %eax)
17966     # push(vars, out-addr->var)
17967     (push *(ebp+0xc) *(edi+0xc))  # Block-var
17968     (push *(ebp+0xc) *(edi+0x10))  # Block-var
17969     (push *(ebp+0xc) 0)  # false
17970     # increment *Curr-block-depth
17971     ff 0/subop/increment *Curr-block-depth
17972     {
17973 $parse-mu-block:line-loop:
17974       # line = read-line-buffered(in)
17975       (clear-stream %ecx)
17976       (read-line-buffered *(ebp+8) %ecx)
17977 #?       (write-buffered Stderr "line: ")
17978 #?       (write-stream-data Stderr %ecx)
17979 #? #?       (write-buffered Stderr Newline)  # line has its own newline
17980 #?       (flush Stderr)
17981 #?       (rewind-stream %ecx)
17982       # if (line->write == 0) break
17983       81 7/subop/compare *ecx 0/imm32
17984       0f 84/jump-if-= break/disp32
17985 #?       (write-buffered Stderr "vars:\n")
17986 #?       (dump-vars *(ebp+0xc))
17987       # word-slice = next-mu-token(line)
17988       (next-mu-token %ecx %edx)
17989 #?       (write-buffered Stderr "word: ")
17990 #?       (write-slice-buffered Stderr %edx)
17991 #?       (write-buffered Stderr Newline)
17992 #?       (flush Stderr)
17993       # if slice-empty?(word-slice) continue
17994       (slice-empty? %edx)
17995       3d/compare-eax-and 0/imm32/false
17996       0f 85/jump-if-!= loop/disp32
17997       # if (slice-starts-with?(word-slice, '#') continue
17998       # . eax = *word-slice->start
17999       8b/-> *edx 0/r32/eax
18000       8a/copy-byte *eax 0/r32/AL
18001       81 4/subop/and %eax 0xff/imm32
18002       # . if (eax == '#') continue
18003       3d/compare-eax-and 0x23/imm32/hash
18004       0f 84/jump-if-= loop/disp32
18005       # if slice-equal?(word-slice, "{")
18006       {
18007 $parse-mu-block:check-for-block:
18008         (slice-equal? %edx "{")
18009         3d/compare-eax-and 0/imm32/false
18010         74/jump-if-= break/disp8
18011         (check-no-tokens-left %ecx)
18012         # parse new block and append
18013         # . var tmp/eax: (handle block)
18014         68/push 0/imm32
18015         68/push 0/imm32
18016         89/<- %eax 4/r32/esp
18017         # .
18018         (parse-mu-block *(ebp+8) *(ebp+0xc) *(ebp+0x10) %eax *(ebp+0x18) *(ebp+0x1c))
18019         (append-to-block Heap %edi  *eax *(eax+4))
18020         # . reclaim tmp
18021         81 0/subop/add %esp 8/imm32
18022         # .
18023         e9/jump $parse-mu-block:line-loop/disp32
18024       }
18025       # if slice-equal?(word-slice, "}") break
18026 $parse-mu-block:check-for-end:
18027       (slice-equal? %edx "}")
18028       3d/compare-eax-and 0/imm32/false
18029       0f 85/jump-if-!= break/disp32
18030       # if slice-ends-with?(word-slice, ":") parse named block and append
18031       {
18032 $parse-mu-block:check-for-named-block:
18033         # . eax = *(word-slice->end-1)
18034         8b/-> *(edx+4) 0/r32/eax
18035         48/decrement-eax
18036         8a/copy-byte *eax 0/r32/AL
18037         81 4/subop/and %eax 0xff/imm32
18038         # . if (eax != ':') break
18039         3d/compare-eax-and 0x3a/imm32/colon
18040         0f 85/jump-if-!= break/disp32
18041         # TODO: error-check the rest of 'line'
18042         #
18043         # skip ':'
18044         ff 1/subop/decrement *(edx+4)  # Slice-end
18045         # var tmp/eax: (handle block)
18046         68/push 0/imm32
18047         68/push 0/imm32
18048         89/<- %eax 4/r32/esp
18049         #
18050         (parse-mu-named-block %edx *(ebp+8) *(ebp+0xc) *(ebp+0x10) %eax *(ebp+0x18) *(ebp+0x1c))
18051         (append-to-block Heap %edi  *eax *(eax+4))
18052         # reclaim tmp
18053         81 0/subop/add %esp 8/imm32
18054         #
18055         e9/jump $parse-mu-block:line-loop/disp32
18056       }
18057       # if slice-equal?(word-slice, "var")
18058       {
18059 $parse-mu-block:check-for-var:
18060         (slice-equal? %edx "var")
18061         3d/compare-eax-and 0/imm32/false
18062         74/jump-if-= break/disp8
18063         # var tmp/eax: (handle block)
18064         68/push 0/imm32
18065         68/push 0/imm32
18066         89/<- %eax 4/r32/esp
18067         #
18068         (parse-mu-var-def %ecx *(ebp+0xc) %eax *(ebp+0x10) *(ebp+0x18) *(ebp+0x1c))
18069         (append-to-block Heap %edi  *eax *(eax+4))
18070         # reclaim tmp
18071         81 0/subop/add %esp 8/imm32
18072         #
18073         e9/jump $parse-mu-block:line-loop/disp32
18074       }
18075 $parse-mu-block:regular-stmt:
18076       # otherwise
18077       # var tmp/eax: (handle block)
18078       68/push 0/imm32
18079       68/push 0/imm32
18080       89/<- %eax 4/r32/esp
18081       #
18082       (parse-mu-stmt %ecx *(ebp+0xc) *(ebp+0x10) %eax *(ebp+0x18) *(ebp+0x1c))
18083       (append-to-block Heap %edi  *eax *(eax+4))
18084       # reclaim tmp
18085       81 0/subop/add %esp 8/imm32
18086       #
18087       e9/jump loop/disp32
18088     } # end line loop
18089     (clean-up-blocks *(ebp+0xc) *Curr-block-depth *(ebp+0x10))
18090     # decrement *Curr-block-depth
18091     ff 1/subop/decrement *Curr-block-depth
18092     # pop(vars)
18093     (pop *(ebp+0xc))  # => eax
18094     (pop *(ebp+0xc))  # => eax
18095     (pop *(ebp+0xc))  # => eax
18096 $parse-mu-block:end:
18097     # . reclaim locals
18098     81 0/subop/add %esp 0x214/imm32
18099     # . restore registers
18100     5f/pop-to-edi
18101     5b/pop-to-ebx
18102     5a/pop-to-edx
18103     59/pop-to-ecx
18104     58/pop-to-eax
18105     # . epilogue
18106     89/<- %esp 5/r32/ebp
18107     5d/pop-to-ebp
18108     c3/return
18109 
18110 $parse-mu-block:abort:
18111     # error("'{' or '}' should be on its own line, but got '")
18112     (write-buffered *(ebp+0x18) "'{' or '}' should be on its own line, but got '")
18113     (rewind-stream %ecx)
18114     (write-stream-data *(ebp+0x18) %ecx)
18115     (write-buffered *(ebp+0x18) "'\n")
18116     (flush *(ebp+0x18))
18117     (stop *(ebp+0x1c) 1)
18118     # never gets here
18119 
18120 new-block-name:  # fn: (addr function), out: (addr handle var)
18121     # . prologue
18122     55/push-ebp
18123     89/<- %ebp 4/r32/esp
18124     # . save registers
18125     50/push-eax
18126     51/push-ecx
18127     52/push-edx
18128     # var n/ecx: int = len(fn->name) + 10 for an int + 2 for '$:'
18129     8b/-> *(ebp+8) 0/r32/eax
18130     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18131     8b/-> *eax 0/r32/eax  # String-size
18132     05/add-to-eax 0xd/imm32  # 10 + 2 for '$:'
18133     89/<- %ecx 0/r32/eax
18134     # var name/edx: (stream byte n)
18135     29/subtract-from %esp 1/r32/ecx
18136     ff 6/subop/push %ecx
18137     68/push 0/imm32/read
18138     68/push 0/imm32/write
18139     89/<- %edx 4/r32/esp
18140     (clear-stream %edx)
18141     # eax = fn->name
18142     8b/-> *(ebp+8) 0/r32/eax
18143     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18144     # construct result using Next-block-index (and increment it)
18145     (write %edx "$")
18146     (write %edx %eax)
18147     (write %edx ":")
18148     (write-int32-hex %edx *Next-block-index)
18149     ff 0/subop/increment *Next-block-index
18150     # var s/eax: slice = {name->data, name->data + name->write}  (clobbering edx)
18151     # . eax = name->write
18152     8b/-> *edx 0/r32/eax
18153     # . edx = name->data
18154     8d/copy-address *(edx+0xc) 2/r32/edx
18155     # . eax = name->write + name->data
18156     01/add-to %eax 2/r32/edx
18157     # . push {edx, eax}
18158     ff 6/subop/push %eax
18159     ff 6/subop/push %edx
18160     89/<- %eax 4/r32/esp
18161     # out = new literal(s)
18162     (new-literal Heap %eax *(ebp+0xc))
18163 #?     8b/-> *(ebp+0xc) 0/r32/eax
18164 #?     (write-buffered Stderr "type allocid in caller after new-literal: ")
18165 #?     (write-int32-hex-buffered Stderr *(eax+8))
18166 #?     (write-buffered Stderr " for var ")
18167 #?     (write-int32-hex-buffered Stderr %eax)
18168 #?     (write-buffered Stderr Newline)
18169 #?     (flush Stderr)
18170 $new-block-name:end:
18171     # . reclaim locals
18172     81 0/subop/add %ecx 0xc/imm32  # name.{read/write/len}
18173     81 0/subop/add %ecx 8/imm32  # slice
18174     01/add-to %esp 1/r32/ecx
18175     # . restore registers
18176     5a/pop-to-edx
18177     59/pop-to-ecx
18178     58/pop-to-eax
18179     # . epilogue
18180     89/<- %esp 5/r32/ebp
18181     5d/pop-to-ebp
18182     c3/return
18183 
18184 check-no-tokens-left:  # line: (addr stream byte)
18185     # . prologue
18186     55/push-ebp
18187     89/<- %ebp 4/r32/esp
18188     # . save registers
18189     50/push-eax
18190     51/push-ecx
18191     # var s/ecx: slice
18192     68/push 0/imm32/end
18193     68/push 0/imm32/start
18194     89/<- %ecx 4/r32/esp
18195     #
18196     (next-mu-token *(ebp+8) %ecx)
18197     # if slice-empty?(s) return
18198     (slice-empty? %ecx)
18199     3d/compare-eax-and 0/imm32/false
18200     75/jump-if-!= $check-no-tokens-left:end/disp8
18201     # if (slice-starts-with?(s, '#') return
18202     # . eax = *s->start
18203     8b/-> *edx 0/r32/eax
18204     8a/copy-byte *eax 0/r32/AL
18205     81 4/subop/and %eax 0xff/imm32
18206     # . if (eax == '#') continue
18207     3d/compare-eax-and 0x23/imm32/hash
18208     74/jump-if-= $check-no-tokens-left:end/disp8
18209     # abort
18210     (write-buffered Stderr "'{' or '}' should be on its own line, but got '")
18211     (rewind-stream %ecx)
18212     (write-stream 2 %ecx)
18213     (write-buffered Stderr "'\n")
18214     (flush Stderr)
18215     # . syscall(exit, 1)
18216     bb/copy-to-ebx  1/imm32
18217     e8/call syscall_exit/disp32
18218     # never gets here
18219 $check-no-tokens-left:end:
18220     # . reclaim locals
18221     81 0/subop/add %esp 8/imm32
18222     # . restore registers
18223     59/pop-to-ecx
18224     58/pop-to-eax
18225     # . epilogue
18226     89/<- %esp 5/r32/ebp
18227     5d/pop-to-ebp
18228     c3/return
18229 
18230 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)
18231     # pseudocode:
18232     #   var v: (handle var)
18233     #   new-literal(name, v)
18234     #   push(vars, {v, false})
18235     #   parse-mu-block(in, vars, fn, out)
18236     #   pop(vars)
18237     #   out->tag = block
18238     #   out->var = v
18239     #
18240     # . prologue
18241     55/push-ebp
18242     89/<- %ebp 4/r32/esp
18243     # . save registers
18244     50/push-eax
18245     51/push-ecx
18246     57/push-edi
18247     # var v/ecx: (handle var)
18248     68/push 0/imm32
18249     68/push 0/imm32
18250     89/<- %ecx 4/r32/esp
18251     #
18252     (new-literal Heap *(ebp+8) %ecx)
18253     # push(vars, v)
18254     (push *(ebp+0x10) *ecx)
18255     (push *(ebp+0x10) *(ecx+4))
18256     (push *(ebp+0x10) 0)  # false
18257     #
18258     (parse-mu-block *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c) *(ebp+0x20))
18259     # pop v off vars
18260     (pop *(ebp+0x10))  # => eax
18261     (pop *(ebp+0x10))  # => eax
18262     (pop *(ebp+0x10))  # => eax
18263     # var out-addr/edi: (addr stmt) = lookup(*out)
18264     8b/-> *(ebp+0x18) 7/r32/edi
18265     (lookup *edi *(edi+4))  # => eax
18266     89/<- %edi 0/r32/eax
18267     # out-addr->tag = named-block
18268     c7 0/subop/copy *edi 0/imm32/block  # Stmt-tag
18269     # out-addr->var = v
18270     8b/-> *ecx 0/r32/eax
18271     89/<- *(edi+0xc) 0/r32/eax  # Block-var
18272     8b/-> *(ecx+4) 0/r32/eax
18273     89/<- *(edi+0x10) 0/r32/eax  # Block-var
18274 $parse-mu-named-block:end:
18275     # . reclaim locals
18276     81 0/subop/add %esp 8/imm32
18277     # . restore registers
18278     5f/pop-to-edi
18279     59/pop-to-ecx
18280     58/pop-to-eax
18281     # . epilogue
18282     89/<- %esp 5/r32/ebp
18283     5d/pop-to-ebp
18284     c3/return
18285 
18286 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)
18287     # . prologue
18288     55/push-ebp
18289     89/<- %ebp 4/r32/esp
18290     # . save registers
18291     50/push-eax
18292     51/push-ecx
18293     52/push-edx
18294     56/push-esi
18295     57/push-edi
18296     # edi = out
18297     8b/-> *(ebp+0x10) 7/r32/edi
18298     # var word-slice/ecx: slice
18299     68/push 0/imm32/end
18300     68/push 0/imm32/start
18301     89/<- %ecx 4/r32/esp
18302     # var v/edx: (handle var)
18303     68/push 0/imm32
18304     68/push 0/imm32
18305     89/<- %edx 4/r32/esp
18306     # v = parse-var-with-type(next-mu-token(line))
18307     (next-mu-token *(ebp+8) %ecx)
18308     {
18309       # just for tests, support null fn
18310       8b/-> *(ebp+0x14) 0/r32/eax
18311       3d/compare-eax-and 0/imm32
18312       74/jump-if-= break/disp8
18313       (lookup *eax *(eax+4))  # Var-name Var-name => eax
18314     }
18315     (parse-var-with-type %ecx *(ebp+8) %edx %eax *(ebp+0x18) *(ebp+0x1c))
18316     # var v-addr/esi: (addr var)
18317     (lookup *edx *(edx+4))  # => eax
18318     89/<- %esi 0/r32/eax
18319     # v->block-depth = *Curr-block-depth
18320     8b/-> *Curr-block-depth 0/r32/eax
18321     89/<- *(esi+0x10) 0/r32/eax  # Var-block-depth
18322     # either v has no register and there's no more to this line
18323     81 7/subop/compare *(esi+0x18) 0/imm32
18324     {
18325       75/jump-if-!= break/disp8
18326       # if v-addr->type == byte, abort
18327       (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
18328       (is-simple-mu-type? %eax 8)  # byte => eax
18329       3d/compare-eax-and 0/imm32/false
18330       0f 85/jump-if-!= $parse-mu-var-def:error-byte-on-stack/disp32
18331       # ensure that there's nothing else on this line
18332       (next-mu-token *(ebp+8) %ecx)
18333       (slice-empty? %ecx)  # => eax
18334       3d/compare-eax-and 0/imm32/false
18335       0f 84/jump-if-= $parse-mu-var-def:error2/disp32
18336       #
18337       (new-var-def Heap  *edx *(edx+4)  %edi)
18338       e9/jump $parse-mu-var-def:update-vars/disp32
18339     }
18340     # or v has a register and there's more to this line
18341     {
18342       0f 84/jump-if-= break/disp32
18343       # if v-addr->type == byte, check for unsupported registers
18344       {
18345         (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
18346         (is-simple-mu-type? %eax 8)  # byte => eax
18347         3d/compare-eax-and 0/imm32/false
18348         74/jump-if-= break/disp8
18349         (lookup *(esi+0x18) *(esi+0x1c))  # => eax
18350         (string-equal? %eax "esi")  # => eax
18351         3d/compare-eax-and 0/imm32/false
18352         0f 85/jump-if-!= $parse-mu-var-def:error-byte-registers/disp32
18353         (lookup *(esi+0x18) *(esi+0x1c))  # => eax
18354         (string-equal? %eax "edi")  # => eax
18355         3d/compare-eax-and 0/imm32/false
18356         0f 85/jump-if-!= $parse-mu-var-def:error-byte-registers/disp32
18357       }
18358       # TODO: vars of type 'byte' should only be initialized by clearing to 0
18359       # ensure that the next word is '<-'
18360       (next-mu-token *(ebp+8) %ecx)
18361       (slice-equal? %ecx "<-")  # => eax
18362       3d/compare-eax-and 0/imm32/false
18363       0f 84/jump-if-= $parse-mu-var-def:error1/disp32
18364       #
18365       (new-reg-var-def Heap  *edx *(edx+4)  %edi)
18366       (lookup *edi *(edi+4))  # => eax
18367       (add-operation-and-inputs-to-stmt %eax *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
18368     }
18369 $parse-mu-var-def:update-vars:
18370     # push 'v' at end of function
18371     (push *(ebp+0xc) *edx)
18372     (push *(ebp+0xc) *(edx+4))
18373     (push *(ebp+0xc) 0)  # Live-var-register-spilled is unused during parsing
18374 $parse-mu-var-def:end:
18375     # . reclaim locals
18376     81 0/subop/add %esp 0x10/imm32
18377     # . restore registers
18378     5f/pop-to-edi
18379     5e/pop-to-esi
18380     5a/pop-to-edx
18381     59/pop-to-ecx
18382     58/pop-to-eax
18383     # . epilogue
18384     89/<- %esp 5/r32/ebp
18385     5d/pop-to-ebp
18386     c3/return
18387 
18388 $parse-mu-var-def:error1:
18389     (rewind-stream *(ebp+8))
18390     # error("register variable requires a valid instruction to initialize but got '" line "'\n")
18391     (write-buffered *(ebp+0x18) "register variable requires a valid instruction to initialize but got '")
18392     (flush *(ebp+0x18))
18393     (write-stream-data *(ebp+0x18) *(ebp+8))
18394     (write-buffered *(ebp+0x18) "'\n")
18395     (flush *(ebp+0x18))
18396     (stop *(ebp+0x1c) 1)
18397     # never gets here
18398 
18399 $parse-mu-var-def:error2:
18400     # error("fn " fn ": var " var ": variables on the stack can't take an initializer\n")
18401     (write-buffered *(ebp+0x18) "fn ")
18402     8b/-> *(ebp+0x14) 0/r32/eax
18403     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18404     (write-buffered *(ebp+0x18) %eax)
18405     (write-buffered *(ebp+0x18) ": var ")
18406     # var v-addr/eax: (addr var) = lookup(v)
18407     (lookup *edx *(edx+4))  # => eax
18408     (lookup *eax *(eax+4))  # Var-name Var-name => eax
18409     (write-buffered *(ebp+0x18) %eax)
18410     (write-buffered *(ebp+0x18) ": variables on the stack can't take an initializer\n")
18411     (flush *(ebp+0x18))
18412     (stop *(ebp+0x1c) 1)
18413     # never gets here
18414 
18415 $parse-mu-var-def:error-byte-on-stack:
18416     # error("fn " fn ": var '" var "' of type 'byte' cannot be on the stack\n")
18417     (write-buffered *(ebp+0x18) "fn ")
18418     8b/-> *(ebp+0x14) 0/r32/eax
18419     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18420     (write-buffered *(ebp+0x18) %eax)
18421     (write-buffered *(ebp+0x18) ": var '")
18422     # var v-addr/eax: (addr var) = lookup(v)
18423     (lookup *edx *(edx+4))  # => eax
18424     (lookup *eax *(eax+4))  # Var-name Var-name => eax
18425     (write-buffered *(ebp+0x18) %eax)
18426     (write-buffered *(ebp+0x18) "' of type 'byte' cannot be on the stack\n")
18427     (flush *(ebp+0x18))
18428     (stop *(ebp+0x1c) 1)
18429     # never gets here
18430 
18431 $parse-mu-var-def:error-byte-registers:
18432     # error("fn " fn ": var '" var "' of type 'byte' cannot be in esi or edi\n")
18433     (write-buffered *(ebp+0x18) "fn ")
18434     8b/-> *(ebp+0x14) 0/r32/eax
18435     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18436     (write-buffered *(ebp+0x18) %eax)
18437     (write-buffered *(ebp+0x18) ": var '")
18438     # var v-addr/eax: (addr var) = lookup(v)
18439     (lookup *edx *(edx+4))  # => eax
18440     (lookup *eax *(eax+4))  # Var-name Var-name => eax
18441     (write-buffered *(ebp+0x18) %eax)
18442     (write-buffered *(ebp+0x18) "' of type 'byte' cannot be in esi or edi\n")
18443     (flush *(ebp+0x18))
18444     (stop *(ebp+0x1c) 1)
18445     # never gets here
18446 
18447 test-parse-mu-var-def:
18448     # 'var n: int'
18449     # . prologue
18450     55/push-ebp
18451     89/<- %ebp 4/r32/esp
18452     # setup
18453     8b/-> *Primitive-type-ids 0/r32/eax
18454     89/<- *Type-id 0/r32/eax  # stream-write
18455     (clear-stream _test-input-stream)
18456     (write _test-input-stream "n: int\n")  # caller has consumed the 'var'
18457     c7 0/subop/copy *Curr-block-depth 1/imm32
18458     # var out/esi: (handle stmt)
18459     68/push 0/imm32
18460     68/push 0/imm32
18461     89/<- %esi 4/r32/esp
18462     # var vars/ecx: (stack (addr var) 16)
18463     81 5/subop/subtract %esp 0xc0/imm32
18464     68/push 0xc0/imm32/size
18465     68/push 0/imm32/top
18466     89/<- %ecx 4/r32/esp
18467     (clear-stack %ecx)
18468     # convert
18469     (parse-mu-var-def _test-input-stream %ecx %esi 0 Stderr 0)
18470     # var out-addr/esi: (addr stmt)
18471     (lookup *esi *(esi+4))  # => eax
18472     89/<- %esi 0/r32/eax
18473     #
18474     (check-ints-equal *esi 2 "F - test-parse-mu-var-def/tag")  # Stmt-tag is var-def
18475     # var v/ecx: (addr var) = lookup(out->var)
18476     (lookup *(esi+4) *(esi+8))  # Vardef-var Vardef-var => eax
18477     89/<- %ecx 0/r32/eax
18478     # v->name
18479     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
18480     (check-strings-equal %eax "n" "F - test-parse-mu-var-def/var-name")
18481     # v->register
18482     (check-ints-equal *(ecx+0x18) 0 "F - test-parse-mu-var-def/var-register")  # Var-register
18483     # v->block-depth
18484     (check-ints-equal *(ecx+0x10) 1 "F - test-parse-mu-var-def/output-block-depth")  # Var-block-depth
18485     # v->type == int
18486     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
18487     (check-ints-equal *eax 1 "F - test-parse-mu-var-def/var-type:0")  # Type-tree-is-atom
18488     (check-ints-equal *(eax+4) 1 "F - test-parse-mu-var-def/var-type:1")  # Type-tree-value
18489     (check-ints-equal *(eax+0xc) 0 "F - test-parse-mu-var-def/var-type:2")  # Type-tree-right
18490     # . epilogue
18491     89/<- %esp 5/r32/ebp
18492     5d/pop-to-ebp
18493     c3/return
18494 
18495 test-parse-mu-reg-var-def:
18496     # 'var n/eax: int <- copy 0'
18497     # . prologue
18498     55/push-ebp
18499     89/<- %ebp 4/r32/esp
18500     # setup
18501     8b/-> *Primitive-type-ids 0/r32/eax
18502     89/<- *Type-id 0/r32/eax  # stream-write
18503     (clear-stream _test-input-stream)
18504     (write _test-input-stream "n/eax: int <- copy 0\n")  # caller has consumed the 'var'
18505     c7 0/subop/copy *Curr-block-depth 1/imm32
18506     # var out/esi: (handle stmt)
18507     68/push 0/imm32
18508     68/push 0/imm32
18509     89/<- %esi 4/r32/esp
18510     # var vars/ecx: (stack (addr var) 16)
18511     81 5/subop/subtract %esp 0xc0/imm32
18512     68/push 0xc0/imm32/size
18513     68/push 0/imm32/top
18514     89/<- %ecx 4/r32/esp
18515     (clear-stack %ecx)
18516     # convert
18517     (parse-mu-var-def _test-input-stream %ecx %esi 0 Stderr 0)
18518     # var out-addr/esi: (addr stmt)
18519     (lookup *esi *(esi+4))  # => eax
18520     89/<- %esi 0/r32/eax
18521     #
18522     (check-ints-equal *esi 3 "F - test-parse-mu-reg-var-def/tag")  # Stmt-tag is reg-var-def
18523     # var v/ecx: (addr var) = lookup(out->outputs->value)
18524     # . eax: (addr stmt-var) = lookup(out->outputs)
18525     (lookup *(esi+0x14) *(esi+0x18))  # Regvardef-outputs Regvardef-outputs => eax
18526     # .
18527     (check-ints-equal *(eax+8) 0 "F - test-parse-mu-reg-var-def/single-output")  # Stmt-var-next
18528     # . eax: (addr var) = lookup(eax->value)
18529     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
18530     # . ecx = eax
18531     89/<- %ecx 0/r32/eax
18532     # v->name
18533     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
18534     (check-strings-equal %eax "n" "F - test-parse-mu-reg-var-def/output-name")  # Var-name
18535     # v->register
18536     (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
18537     (check-strings-equal %eax "eax" "F - test-parse-mu-reg-var-def/output-register")
18538     # v->block-depth
18539     (check-ints-equal *(ecx+0x10) 1 "F - test-parse-mu-reg-var-def/output-block-depth")  # Var-block-depth
18540     # v->type == int
18541     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
18542     (check-ints-equal *eax 1 "F - test-parse-mu-reg-var-def/output-type:0")  # Type-tree-is-atom
18543     (check-ints-equal *(eax+4) 1 "F - test-parse-mu-reg-var-def/output-type:1")  # Type-tree-value
18544     (check-ints-equal *(eax+0xc) 0 "F - test-parse-mu-reg-var-def/output-type:2")  # Type-tree-right
18545     # . epilogue
18546     89/<- %esp 5/r32/ebp
18547     5d/pop-to-ebp
18548     c3/return
18549 
18550 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)
18551     # pseudocode:
18552     #   var name: slice
18553     #   allocate(Heap, Stmt-size, out)
18554     #   var out-addr: (addr stmt) = lookup(*out)
18555     #   out-addr->tag = stmt
18556     #   if stmt-has-outputs?(line)
18557     #     while true
18558     #       name = next-mu-token(line)
18559     #       if (name == '<-') break
18560     #       assert(is-identifier?(name))
18561     #       var v: (handle var) = lookup-var(name, vars)
18562     #       out-addr->outputs = append(v, out-addr->outputs)
18563     #   add-operation-and-inputs-to-stmt(out-addr, line, vars)
18564     #
18565     # . prologue
18566     55/push-ebp
18567     89/<- %ebp 4/r32/esp
18568     # . save registers
18569     50/push-eax
18570     51/push-ecx
18571     52/push-edx
18572     53/push-ebx
18573     57/push-edi
18574     # var name/ecx: slice
18575     68/push 0/imm32/end
18576     68/push 0/imm32/start
18577     89/<- %ecx 4/r32/esp
18578     # var is-deref?/edx: boolean = false
18579     ba/copy-to-edx 0/imm32/false
18580     # var v: (handle var)
18581     68/push 0/imm32
18582     68/push 0/imm32
18583     89/<- %ebx 4/r32/esp
18584     #
18585     (allocate Heap *Stmt-size *(ebp+0x14))
18586     # var out-addr/edi: (addr stmt) = lookup(*out)
18587     8b/-> *(ebp+0x14) 7/r32/edi
18588     (lookup *edi *(edi+4))  # => eax
18589     89/<- %edi 0/r32/eax
18590     # out-addr->tag = 1/stmt
18591     c7 0/subop/copy *edi 1/imm32/stmt1  # Stmt-tag
18592     {
18593       (stmt-has-outputs? *(ebp+8))
18594       3d/compare-eax-and 0/imm32/false
18595       0f 84/jump-if-= break/disp32
18596       {
18597 $parse-mu-stmt:read-outputs:
18598         # name = next-mu-token(line)
18599         (next-mu-token *(ebp+8) %ecx)
18600         # if slice-empty?(word-slice) break
18601         (slice-empty? %ecx)  # => eax
18602         3d/compare-eax-and 0/imm32/false
18603         0f 85/jump-if-!= break/disp32
18604         # if (name == "<-") break
18605         (slice-equal? %ecx "<-")  # => eax
18606         3d/compare-eax-and 0/imm32/false
18607         0f 85/jump-if-!= break/disp32
18608         # if slice-starts-with?(name, "*") abort
18609         8b/-> *ecx 0/r32/eax  # Slice-start
18610         8a/copy-byte *eax 0/r32/AL
18611         81 4/subop/and %eax 0xff/imm32
18612         3d/compare-eax-and 0x2a/imm32/asterisk
18613         0f 84/jump-if-= $parse-mu-stmt:error-output-dereferenced/disp32
18614         # assert(is-identifier?(name))
18615         (is-identifier? %ecx)  # => eax
18616         3d/compare-eax-and 0/imm32/false
18617         0f 84/jump-if-= $parse-mu-stmt:abort/disp32
18618         #
18619         (lookup-var %ecx *(ebp+0xc) %ebx *(ebp+0x10) *(ebp+0x18) *(ebp+0x1c))
18620         8d/copy-address *(edi+0x14) 0/r32/eax  # Stmt1-outputs
18621         (append-stmt-var Heap  *ebx *(ebx+4)  *(edi+0x14) *(edi+0x18)  0  %eax)  # Stmt1-outputs
18622         #
18623         e9/jump loop/disp32
18624       }
18625     }
18626     (add-operation-and-inputs-to-stmt %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x18) *(ebp+0x1c))
18627 $parse-mu-stmt:end:
18628     # . reclaim locals
18629     81 0/subop/add %esp 0x10/imm32
18630     # . restore registers
18631     5f/pop-to-edi
18632     5b/pop-to-ebx
18633     5a/pop-to-edx
18634     59/pop-to-ecx
18635     58/pop-to-eax
18636     # . epilogue
18637     89/<- %esp 5/r32/ebp
18638     5d/pop-to-ebp
18639     c3/return
18640 
18641 $parse-mu-stmt:abort:
18642     # error("invalid identifier '" name "'\n")
18643     (write-buffered *(ebp+0x18) "fn ")
18644     8b/-> *(ebp+0x10) 0/r32/eax
18645     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18646     (write-buffered *(ebp+0x18) %eax)
18647     (write-buffered *(ebp+0x18) ": invalid identifier '")
18648     (write-slice-buffered *(ebp+0x18) %ecx)
18649     (write-buffered *(ebp+0x18) "'\n")
18650     (flush *(ebp+0x18))
18651     (stop *(ebp+0x1c) 1)
18652     # never gets here
18653 
18654 $parse-mu-stmt:error-output-dereferenced:
18655     # error("invalid identifier '" name "'\n")
18656     (write-buffered *(ebp+0x18) "fn ")
18657     8b/-> *(ebp+0x10) 0/r32/eax
18658     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18659     (write-buffered *(ebp+0x18) %eax)
18660     (write-buffered *(ebp+0x18) ": output '")
18661     (write-slice-buffered *(ebp+0x18) %ecx)
18662     (write-buffered *(ebp+0x18) "' should write to a register, and therefore cannot be dereferenced\n")
18663     (flush *(ebp+0x18))
18664     (stop *(ebp+0x1c) 1)
18665     # never gets here
18666 
18667 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)
18668     # pseudocode:
18669     #   stmt->name = slice-to-string(next-mu-token(line))
18670     #   while true
18671     #     name = next-mu-token(line)
18672     #     v = lookup-var-or-literal(name)
18673     #     stmt->inouts = append(v, stmt->inouts)
18674     #
18675     # . prologue
18676     55/push-ebp
18677     89/<- %ebp 4/r32/esp
18678     # . save registers
18679     50/push-eax
18680     51/push-ecx
18681     52/push-edx
18682     53/push-ebx
18683     56/push-esi
18684     57/push-edi
18685     # edi = stmt
18686     8b/-> *(ebp+8) 7/r32/edi
18687     # var name/ecx: slice
18688     68/push 0/imm32/end
18689     68/push 0/imm32/start
18690     89/<- %ecx 4/r32/esp
18691     # var is-deref?/edx: boolean = false
18692     ba/copy-to-edx 0/imm32/false
18693     # var v/esi: (handle var)
18694     68/push 0/imm32
18695     68/push 0/imm32
18696     89/<- %esi 4/r32/esp
18697 $add-operation-and-inputs-to-stmt:read-operation:
18698     (next-mu-token *(ebp+0xc) %ecx)
18699     8d/copy-address *(edi+4) 0/r32/eax  # Stmt1-operation or Regvardef-operationStmt1-operation or Regvardef-operation
18700     (slice-to-string Heap %ecx %eax)
18701     # var is-get?/ebx: boolean = (name == "get")
18702     (slice-equal? %ecx "get")  # => eax
18703     89/<- %ebx 0/r32/eax
18704     {
18705 $add-operation-and-inputs-to-stmt:read-inouts:
18706       # name = next-mu-token(line)
18707       (next-mu-token *(ebp+0xc) %ecx)
18708       # if slice-empty?(word-slice) break
18709       (slice-empty? %ecx)  # => eax
18710       3d/compare-eax-and 0/imm32/false
18711       0f 85/jump-if-!= break/disp32
18712       # if (name == "<-") abort
18713       (slice-equal? %ecx "<-")
18714       3d/compare-eax-and 0/imm32/false
18715       0f 85/jump-if-!= $add-operation-and-inputs-to-stmt:abort/disp32
18716       # if (is-get? && second operand) lookup or create offset
18717       {
18718         81 7/subop/compare %ebx 0/imm32/false
18719         74/jump-if-= break/disp8
18720         (lookup *(edi+0xc) *(edi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
18721         3d/compare-eax-and 0/imm32
18722         74/jump-if-= break/disp8
18723         (lookup-or-create-constant %eax %ecx %esi)
18724 #?         (lookup *esi *(esi+4))
18725 #?         (write-buffered Stderr "creating new output var ")
18726 #?         (write-int32-hex-buffered Stderr %eax)
18727 #?         (write-buffered Stderr " for field called ")
18728 #?         (write-slice-buffered Stderr %ecx)
18729 #?         (write-buffered Stderr "; var name ")
18730 #?         (lookup *eax *(eax+4))  # Var-name
18731 #?         (write-buffered Stderr %eax)
18732 #?         (write-buffered Stderr Newline)
18733 #?         (flush Stderr)
18734         e9/jump $add-operation-and-inputs-to-stmt:save-var/disp32
18735       }
18736       # is-deref? = false
18737       ba/copy-to-edx 0/imm32/false
18738       # if (slice-starts-with?(name, '*')) ++name->start and set is-deref?
18739       8b/-> *ecx 0/r32/eax  # Slice-start
18740       8a/copy-byte *eax 0/r32/AL
18741       81 4/subop/and %eax 0xff/imm32
18742       3d/compare-eax-and 0x2a/imm32/asterisk
18743       {
18744         75/jump-if-!= break/disp8
18745 $add-operation-and-inputs-to-stmt:inout-is-deref:
18746         ff 0/subop/increment *ecx
18747         ba/copy-to-edx 1/imm32/true
18748       }
18749       (lookup-var-or-literal %ecx *(ebp+0x10) %esi *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
18750       # if (is-deref?) some additional checks
18751       81 7/subop/compare %edx 0/imm32/false
18752       {
18753         74/jump-if-= break/disp8
18754         # if var is not in register, abort
18755         (lookup *esi *(esi+4))  # => eax
18756         81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
18757         0f 84/jump-if-= $add-operation-and-inputs-to-stmt:error-deref-on-stack/disp32
18758         # if var is not an address, abort
18759         (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
18760         (is-mu-addr-type? %eax)  # => eax
18761         3d/compare-eax-and 0/imm32/false
18762         0f 84/jump-if-= $add-operation-and-inputs-to-stmt:error-deref-non-addr/disp32
18763       }
18764 $add-operation-and-inputs-to-stmt:save-var:
18765       8d/copy-address *(edi+0xc) 0/r32/eax
18766       (append-stmt-var Heap  *esi *(esi+4)  *(edi+0xc) *(edi+0x10)  %edx  %eax)  # Stmt1-inouts or Regvardef-inouts
18767       #
18768       e9/jump loop/disp32
18769     }
18770 $add-operation-and-inputs-to-stmt:end:
18771     # . reclaim locals
18772     81 0/subop/add %esp 0x10/imm32
18773     # . restore registers
18774     5f/pop-to-edi
18775     5e/pop-to-esi
18776     5b/pop-to-ebx
18777     5a/pop-to-edx
18778     59/pop-to-ecx
18779     58/pop-to-eax
18780     # . epilogue
18781     89/<- %esp 5/r32/ebp
18782     5d/pop-to-ebp
18783     c3/return
18784 
18785 $add-operation-and-inputs-to-stmt:abort:
18786     # error("fn ___: invalid identifier in '" line "'\n")
18787     (write-buffered *(ebp+0x18) "fn ")
18788     8b/-> *(ebp+0x14) 0/r32/eax
18789     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18790     (write-buffered *(ebp+0x18) %eax)
18791     (rewind-stream *(ebp+0xc))
18792     (write-buffered *(ebp+0x18) ": invalid identifier in '")
18793     (write-stream-data *(ebp+0x18) *(ebp+0xc))
18794     (write-buffered *(ebp+0x18) "'\n")
18795     (flush *(ebp+0x18))
18796     (stop *(ebp+0x1c) 1)
18797     # never gets here
18798 
18799 $add-operation-and-inputs-to-stmt:error-deref-on-stack:
18800     # error("fn ___: cannot dereference var ___ on stack\n")
18801     (write-buffered *(ebp+0x18) "fn ")
18802     8b/-> *(ebp+0x14) 0/r32/eax
18803     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18804     (write-buffered *(ebp+0x18) %eax)
18805     (rewind-stream *(ebp+0xc))
18806     (write-buffered *(ebp+0x18) ": cannot dereference var '")
18807     (lookup *esi *(esi+4))  # => eax
18808     (lookup *eax *(eax+4))  # Var-name Var-name => eax
18809     (write-buffered *(ebp+0x18) %eax)
18810     (write-buffered *(ebp+0x18) "' on stack\n")
18811     (flush *(ebp+0x18))
18812     (stop *(ebp+0x1c) 1)
18813     # never gets here
18814 
18815 $add-operation-and-inputs-to-stmt:error-deref-non-addr:
18816     # error("fn ___: cannot dereference non-addr var ___\n")
18817     (write-buffered *(ebp+0x18) "fn ")
18818     8b/-> *(ebp+0x14) 0/r32/eax
18819     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18820     (write-buffered *(ebp+0x18) %eax)
18821     (rewind-stream *(ebp+0xc))
18822     (write-buffered *(ebp+0x18) ": cannot dereference non-addr var '")
18823     (lookup *esi *(esi+4))  # => eax
18824     (lookup *eax *(eax+4))  # Var-name Var-name => eax
18825     (write-buffered *(ebp+0x18) %eax)
18826     (write-buffered *(ebp+0x18) "'\n")
18827     (flush *(ebp+0x18))
18828     (stop *(ebp+0x1c) 1)
18829     # never gets here
18830 
18831 stmt-has-outputs?:  # line: (addr stream byte) -> result/eax: boolean
18832     # . prologue
18833     55/push-ebp
18834     89/<- %ebp 4/r32/esp
18835     # . save registers
18836     51/push-ecx
18837     # var word-slice/ecx: slice
18838     68/push 0/imm32/end
18839     68/push 0/imm32/start
18840     89/<- %ecx 4/r32/esp
18841     # result = false
18842     b8/copy-to-eax 0/imm32/false
18843     (rewind-stream *(ebp+8))
18844     {
18845       (next-mu-token *(ebp+8) %ecx)
18846       # if slice-empty?(word-slice) break
18847       (slice-empty? %ecx)
18848       3d/compare-eax-and 0/imm32/false
18849       b8/copy-to-eax 0/imm32/false/result  # restore result (if we're here it's still false)
18850       0f 85/jump-if-!= break/disp32
18851       # if slice-starts-with?(word-slice, '#') break
18852       # . eax = *word-slice->start
18853       8b/-> *ecx 0/r32/eax
18854       8a/copy-byte *eax 0/r32/AL
18855       81 4/subop/and %eax 0xff/imm32
18856       # . if (eax == '#') break
18857       3d/compare-eax-and 0x23/imm32/hash
18858       b8/copy-to-eax 0/imm32/false/result  # restore result (if we're here it's still false)
18859       0f 84/jump-if-= break/disp32
18860       # if slice-equal?(word-slice, '<-') return true
18861       (slice-equal? %ecx "<-")
18862       3d/compare-eax-and 0/imm32/false
18863       74/jump-if-= loop/disp8
18864       b8/copy-to-eax 1/imm32/true
18865     }
18866 $stmt-has-outputs:end:
18867     (rewind-stream *(ebp+8))
18868     # . reclaim locals
18869     81 0/subop/add %esp 8/imm32
18870     # . restore registers
18871     59/pop-to-ecx
18872     # . epilogue
18873     89/<- %esp 5/r32/ebp
18874     5d/pop-to-ebp
18875     c3/return
18876 
18877 # if 'name' starts with a digit, create a new literal var for it
18878 # otherwise return first 'name' from the top (back) of 'vars' and abort if not found
18879 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)
18880     # . prologue
18881     55/push-ebp
18882     89/<- %ebp 4/r32/esp
18883     # . save registers
18884     50/push-eax
18885     51/push-ecx
18886     56/push-esi
18887     # esi = name
18888     8b/-> *(ebp+8) 6/r32/esi
18889     # if slice-empty?(name) abort
18890     (slice-empty? %esi)  # => eax
18891     3d/compare-eax-and 0/imm32/false
18892     0f 85/jump-if-!= $lookup-var-or-literal:abort/disp32
18893     # var c/ecx: byte = *name->start
18894     8b/-> *esi 1/r32/ecx
18895     8a/copy-byte *ecx 1/r32/CL
18896     81 4/subop/and %ecx 0xff/imm32
18897     # if (is-decimal-digit?(c) || c == '-') return new var(name)
18898     {
18899       81 7/subop/compare %ecx 0x2d/imm32/dash
18900       74/jump-if-= $lookup-var-or-literal:literal/disp8
18901       (is-decimal-digit? %ecx)  # => eax
18902       3d/compare-eax-and 0/imm32/false
18903       74/jump-if-= break/disp8
18904 $lookup-var-or-literal:literal:
18905       (new-literal-integer Heap %esi *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
18906       eb/jump $lookup-var-or-literal:end/disp8
18907     }
18908     # else if (c == '"') return new var(name)
18909     {
18910       81 7/subop/compare %ecx 0x22/imm32/dquote
18911       75/jump-if-!= break/disp8
18912 $lookup-var-or-literal:literal-string:
18913       (new-literal-string Heap %esi *(ebp+0x10))
18914       eb/jump $lookup-var-or-literal:end/disp8
18915     }
18916     # otherwise return lookup-var(name, vars)
18917     {
18918 $lookup-var-or-literal:var:
18919       (lookup-var %esi *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
18920     }
18921 $lookup-var-or-literal:end:
18922     # . restore registers
18923     5e/pop-to-esi
18924     59/pop-to-ecx
18925     58/pop-to-eax
18926     # . epilogue
18927     89/<- %esp 5/r32/ebp
18928     5d/pop-to-ebp
18929     c3/return
18930 
18931 $lookup-var-or-literal:abort:
18932     (write-buffered *(ebp+0x18) "fn ")
18933     8b/-> *(ebp+0x14) 0/r32/eax
18934     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18935     (write-buffered *(ebp+0x18) %eax)
18936     (write-buffered *(ebp+0x18) ": empty variable!")
18937     (flush *(ebp+0x18))
18938     (stop *(ebp+0x1c) 1)
18939     # never gets here
18940 
18941 # return first 'name' from the top (back) of 'vars' and abort if not found
18942 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)
18943     # . prologue
18944     55/push-ebp
18945     89/<- %ebp 4/r32/esp
18946     # . save registers
18947     50/push-eax
18948     #
18949     (lookup-var-helper *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
18950     # if (*out == 0) abort
18951     8b/-> *(ebp+0x10) 0/r32/eax
18952     81 7/subop/compare *eax 0/imm32
18953     74/jump-if-= $lookup-var:abort/disp8
18954 $lookup-var:end:
18955     # . restore registers
18956     58/pop-to-eax
18957     # . epilogue
18958     89/<- %esp 5/r32/ebp
18959     5d/pop-to-ebp
18960     c3/return
18961 
18962 $lookup-var:abort:
18963     (write-buffered *(ebp+0x18) "fn ")
18964     8b/-> *(ebp+0x14) 0/r32/eax
18965     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18966     (write-buffered *(ebp+0x18) %eax)
18967     (write-buffered *(ebp+0x18) ": unknown variable '")
18968     (write-slice-buffered *(ebp+0x18) *(ebp+8))
18969     (write-buffered *(ebp+0x18) "'\n")
18970     (flush *(ebp+0x18))
18971     (stop *(ebp+0x1c) 1)
18972     # never gets here
18973 
18974 # return first 'name' from the top (back) of 'vars', and 0/null if not found
18975 # ensure that 'name' if in a register is the topmost variable in that register
18976 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)
18977     # pseudocode:
18978     #   var curr: (addr handle var) = &vars->data[vars->top - 12]
18979     #   var min = vars->data
18980     #   while curr >= min
18981     #     var v: (handle var) = *curr
18982     #     if v->name == name
18983     #       return
18984     #     curr -= 12
18985     #
18986     # . prologue
18987     55/push-ebp
18988     89/<- %ebp 4/r32/esp
18989     # . save registers
18990     50/push-eax
18991     51/push-ecx
18992     52/push-edx
18993     53/push-ebx
18994     56/push-esi
18995     57/push-edi
18996     # clear out
18997     (zero-out *(ebp+0x10) *Handle-size)
18998     # esi = vars
18999     8b/-> *(ebp+0xc) 6/r32/esi
19000     # ebx = vars->top
19001     8b/-> *esi 3/r32/ebx
19002     # if (vars->top > vars->size) abort
19003     3b/compare<- *(esi+4) 0/r32/eax
19004     0f 8f/jump-if-> $lookup-var-helper:error1/disp32
19005     # var min/edx: (addr handle var) = vars->data
19006     8d/copy-address *(esi+8) 2/r32/edx
19007     # var curr/ebx: (addr handle var) = &vars->data[vars->top - 12]
19008     8d/copy-address *(esi+ebx-4) 3/r32/ebx  # vars + 8 + vars->type - 12
19009     # var var-in-reg/edi: 16 addrs
19010     68/push 0/imm32
19011     68/push 0/imm32
19012     68/push 0/imm32
19013     68/push 0/imm32
19014     68/push 0/imm32
19015     68/push 0/imm32
19016     68/push 0/imm32
19017     68/push 0/imm32
19018     68/push 0/imm32
19019     68/push 0/imm32
19020     68/push 0/imm32
19021     68/push 0/imm32
19022     68/push 0/imm32
19023     68/push 0/imm32
19024     68/push 0/imm32
19025     68/push 0/imm32
19026     89/<- %edi 4/r32/esp
19027     {
19028 $lookup-var-helper:loop:
19029       # if (curr < min) return
19030       39/compare %ebx 2/r32/edx
19031       0f 82/jump-if-addr< break/disp32
19032       # var v/ecx: (addr var) = lookup(*curr)
19033       (lookup *ebx *(ebx+4))  # => eax
19034       89/<- %ecx 0/r32/eax
19035       # var vn/eax: (addr array byte) = lookup(v->name)
19036       (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
19037       # if (vn == name) return curr
19038       (slice-equal? *(ebp+8) %eax)  # => eax
19039       3d/compare-eax-and 0/imm32/false
19040       {
19041         74/jump-if-= break/disp8
19042 $lookup-var-helper:found:
19043         # var vr/eax: (addr array byte) = lookup(v->register)
19044         (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
19045         3d/compare-eax-and 0/imm32
19046         {
19047           74/jump-if-= break/disp8
19048 $lookup-var-helper:found-register:
19049           # var reg/eax: int = get(Registers, vr)
19050           (get Mu-registers-unique %eax 0xc "Mu-registers-unique")  # => eax
19051           8b/-> *eax 0/r32/eax
19052           # if (var-in-reg[reg]) error
19053           8b/-> *(edi+eax<<2) 0/r32/eax
19054           3d/compare-eax-and 0/imm32
19055           0f 85/jump-if-!= $lookup-var-helper:error2/disp32
19056         }
19057 $lookup-var-helper:return:
19058         # esi = out
19059         8b/-> *(ebp+0x10) 6/r32/esi
19060         # *out = *curr
19061         8b/-> *ebx 0/r32/eax
19062         89/<- *esi 0/r32/eax
19063         8b/-> *(ebx+4) 0/r32/eax
19064         89/<- *(esi+4) 0/r32/eax
19065         # return
19066         eb/jump $lookup-var-helper:end/disp8
19067       }
19068       # 'name' not yet found; update var-in-reg if v in register
19069       # . var vr/eax: (addr array byte) = lookup(v->register)
19070       (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
19071       # . if (vr == 0) continue
19072       3d/compare-eax-and 0/imm32
19073       74/jump-if-= $lookup-var-helper:continue/disp8
19074       # . var reg/eax: int = get(Registers, vr)
19075       (get Mu-registers-unique %eax 0xc "Mu-registers-unique")  # => eax
19076       8b/-> *eax 0/r32/eax
19077       # . var-in-reg[reg] = v
19078       89/<- *(edi+eax<<2) 1/r32/ecx
19079 $lookup-var-helper:continue:
19080       # curr -= 12
19081       81 5/subop/subtract %ebx 0xc/imm32
19082       e9/jump loop/disp32
19083     }
19084 $lookup-var-helper:end:
19085     # . reclaim locals
19086     81 0/subop/add %esp 0x40/imm32
19087     # . restore registers
19088     5f/pop-to-edi
19089     5e/pop-to-esi
19090     5b/pop-to-ebx
19091     5a/pop-to-edx
19092     59/pop-to-ecx
19093     58/pop-to-eax
19094     # . epilogue
19095     89/<- %esp 5/r32/ebp
19096     5d/pop-to-ebp
19097     c3/return
19098 
19099 $lookup-var-helper:error1:
19100     (write-buffered *(ebp+0x18) "fn ")
19101     8b/-> *(ebp+0x14) 0/r32/eax
19102     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19103     (write-buffered *(ebp+0x18) %eax)
19104     (write-buffered *(ebp+0x18) ": malformed stack when looking up '")
19105     (write-slice-buffered *(ebp+0x18) *(ebp+8))
19106     (write-buffered *(ebp+0x18) "'\n")
19107     (flush *(ebp+0x18))
19108     (stop *(ebp+0x1c) 1)
19109     # never gets here
19110 
19111 $lookup-var-helper:error2:
19112     # eax contains the conflicting var at this point
19113     (write-buffered *(ebp+0x18) "fn ")
19114     50/push-eax
19115     8b/-> *(ebp+0x14) 0/r32/eax
19116     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19117     (write-buffered *(ebp+0x18) %eax)
19118     58/pop-eax
19119     (write-buffered *(ebp+0x18) ": register ")
19120     50/push-eax
19121     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
19122     (write-buffered *(ebp+0x18) %eax)
19123     58/pop-to-eax
19124     (write-buffered *(ebp+0x18) " reads var '")
19125     (write-slice-buffered *(ebp+0x18) *(ebp+8))
19126     (write-buffered *(ebp+0x18) "' after writing var '")
19127     (lookup *eax *(eax+4))  # Var-name Var-name => eax
19128     (write-buffered *(ebp+0x18) %eax)
19129     (write-buffered *(ebp+0x18) "'\n")
19130     (flush *(ebp+0x18))
19131     (stop *(ebp+0x1c) 1)
19132     # never gets here
19133 
19134 dump-vars:  # vars: (addr stack live-var)
19135     # pseudocode:
19136     #   var curr: (addr handle var) = &vars->data[vars->top - 12]
19137     #   var min = vars->data
19138     #   while curr >= min
19139     #     var v: (handle var) = *curr
19140     #     print v
19141     #     curr -= 12
19142     #
19143     # . prologue
19144     55/push-ebp
19145     89/<- %ebp 4/r32/esp
19146     # . save registers
19147     52/push-edx
19148     53/push-ebx
19149     56/push-esi
19150     # esi = vars
19151     8b/-> *(ebp+8) 6/r32/esi
19152     # ebx = vars->top
19153     8b/-> *esi 3/r32/ebx
19154     # var min/edx: (addr handle var) = vars->data
19155     8d/copy-address *(esi+8) 2/r32/edx
19156     # var curr/ebx: (addr handle var) = &vars->data[vars->top - 12]
19157     8d/copy-address *(esi+ebx-4) 3/r32/ebx  # vars + 8 + vars->type - 12
19158     {
19159 $dump-vars:loop:
19160       # if (curr < min) return
19161       39/compare %ebx 2/r32/edx
19162       0f 82/jump-if-addr< break/disp32
19163       #
19164       (write-buffered Stderr "  var@")
19165       (dump-var 2 %ebx)
19166       # curr -= 12
19167       81 5/subop/subtract %ebx 0xc/imm32
19168       e9/jump loop/disp32
19169     }
19170 $dump-vars:end:
19171     # . restore registers
19172     5e/pop-to-esi
19173     5b/pop-to-ebx
19174     5a/pop-to-edx
19175     # . epilogue
19176     89/<- %esp 5/r32/ebp
19177     5d/pop-to-ebp
19178     c3/return
19179 
19180 == data
19181 # Like Registers, but no esp or ebp
19182 Mu-registers:  # (addr stream {(handle array byte), int})
19183   # a table is a stream
19184   0xa8/imm32/write
19185   0/imm32/read
19186   0xa8/imm32/length
19187   # data
19188   # general-purpose registers
19189   # it is perfectly ok to use fake alloc-ids -- as long as you never try to reclaim them
19190   0x11/imm32/alloc-id $Mu-register-eax/imm32 0/imm32
19191   0x11/imm32/alloc-id $Mu-register-ecx/imm32 1/imm32
19192   0x11/imm32/alloc-id $Mu-register-edx/imm32 2/imm32
19193   0x11/imm32/alloc-id $Mu-register-ebx/imm32 3/imm32
19194   0x11/imm32/alloc-id $Mu-register-esi/imm32 6/imm32
19195   0x11/imm32/alloc-id $Mu-register-edi/imm32 7/imm32
19196   # floating-point registers
19197   0x11/imm32/alloc-id $Mu-register-xmm0/imm32 0/imm32
19198   0x11/imm32/alloc-id $Mu-register-xmm1/imm32 1/imm32
19199   0x11/imm32/alloc-id $Mu-register-xmm2/imm32 2/imm32
19200   0x11/imm32/alloc-id $Mu-register-xmm3/imm32 3/imm32
19201   0x11/imm32/alloc-id $Mu-register-xmm4/imm32 4/imm32
19202   0x11/imm32/alloc-id $Mu-register-xmm5/imm32 5/imm32
19203   0x11/imm32/alloc-id $Mu-register-xmm6/imm32 6/imm32
19204   0x11/imm32/alloc-id $Mu-register-xmm7/imm32 7/imm32
19205 
19206 # Like Mu-registers, but with unique codes for integer and floating-point
19207 # registers.
19208 # Don't use this for code-generation, only for checking.
19209 Mu-registers-unique:  # (addr stream {(handle array byte), int})
19210   # a table is a stream
19211   0xa8/imm32/write
19212   0/imm32/read
19213   0xa8/imm32/length
19214   # data
19215   # general-purpose registers
19216   0x11/imm32/alloc-id $Mu-register-eax/imm32 0/imm32
19217   0x11/imm32/alloc-id $Mu-register-ecx/imm32 1/imm32
19218   0x11/imm32/alloc-id $Mu-register-edx/imm32 2/imm32
19219   0x11/imm32/alloc-id $Mu-register-ebx/imm32 3/imm32
19220   0x11/imm32/alloc-id $Mu-register-esi/imm32 6/imm32
19221   0x11/imm32/alloc-id $Mu-register-edi/imm32 7/imm32
19222   # floating-point registers
19223   0x11/imm32/alloc-id $Mu-register-xmm0/imm32 8/imm32
19224   0x11/imm32/alloc-id $Mu-register-xmm1/imm32 9/imm32
19225   0x11/imm32/alloc-id $Mu-register-xmm2/imm32 0xa/imm32
19226   0x11/imm32/alloc-id $Mu-register-xmm3/imm32 0xb/imm32
19227   0x11/imm32/alloc-id $Mu-register-xmm4/imm32 0xc/imm32
19228   0x11/imm32/alloc-id $Mu-register-xmm5/imm32 0xd/imm32
19229   0x11/imm32/alloc-id $Mu-register-xmm6/imm32 0xe/imm32
19230   0x11/imm32/alloc-id $Mu-register-xmm7/imm32 0xf/imm32
19231 
19232 $Mu-register-eax:
19233   0x11/imm32/alloc-id
19234   3/imm32/size
19235   0x65/e 0x61/a 0x78/x
19236 
19237 $Mu-register-ecx:
19238   0x11/imm32/alloc-id
19239   3/imm32/size
19240   0x65/e 0x63/c 0x78/x
19241 
19242 $Mu-register-edx:
19243   0x11/imm32/alloc-id
19244   3/imm32/size
19245   0x65/e 0x64/d 0x78/x
19246 
19247 $Mu-register-ebx:
19248   0x11/imm32/alloc-id
19249   3/imm32/size
19250   0x65/e 0x62/b 0x78/x
19251 
19252 $Mu-register-esi:
19253   0x11/imm32/alloc-id
19254   3/imm32/size
19255   0x65/e 0x73/s 0x69/i
19256 
19257 $Mu-register-edi:
19258   0x11/imm32/alloc-id
19259   3/imm32/size
19260   0x65/e 0x64/d 0x69/i
19261 
19262 $Mu-register-xmm0:
19263   0x11/imm32/alloc-id:fake:payload
19264   # "xmm0"
19265   0x4/imm32/size
19266   0x78/x 0x6d/m 0x6d/m 0x30/0
19267 
19268 $Mu-register-xmm1:
19269   0x11/imm32/alloc-id:fake:payload
19270   # "xmm1"
19271   0x4/imm32/size
19272   0x78/x 0x6d/m 0x6d/m 0x31/1
19273 
19274 $Mu-register-xmm2:
19275   0x11/imm32/alloc-id:fake:payload
19276   # "xmm2"
19277   0x4/imm32/size
19278   0x78/x 0x6d/m 0x6d/m 0x32/2
19279 
19280 $Mu-register-xmm3:
19281   0x11/imm32/alloc-id:fake:payload
19282   # "xmm3"
19283   0x4/imm32/size
19284   0x78/x 0x6d/m 0x6d/m 0x33/3
19285 
19286 $Mu-register-xmm4:
19287   0x11/imm32/alloc-id:fake:payload
19288   # "xmm4"
19289   0x4/imm32/size
19290   0x78/x 0x6d/m 0x6d/m 0x34/4
19291 
19292 $Mu-register-xmm5:
19293   0x11/imm32/alloc-id:fake:payload
19294   # "xmm5"
19295   0x4/imm32/size
19296   0x78/x 0x6d/m 0x6d/m 0x35/5
19297 
19298 $Mu-register-xmm6:
19299   0x11/imm32/alloc-id:fake:payload
19300   # "xmm6"
19301   0x4/imm32/size
19302   0x78/x 0x6d/m 0x6d/m 0x36/6
19303 
19304 $Mu-register-xmm7:
19305   0x11/imm32/alloc-id:fake:payload
19306   # "xmm7"
19307   0x4/imm32/size
19308   0x78/x 0x6d/m 0x6d/m 0x37/7
19309 
19310 == code
19311 
19312 # push 'out' to 'vars' if not already there; it's assumed to be a fn output
19313 maybe-define-var:  # out: (handle var), vars: (addr stack live-var)
19314     # . prologue
19315     55/push-ebp
19316     89/<- %ebp 4/r32/esp
19317     # . save registers
19318     50/push-eax
19319     # var out-addr/eax: (addr var)
19320     (lookup *(ebp+8) *(ebp+0xc))  # => eax
19321     #
19322     (binding-exists? %eax *(ebp+0x10))  # => eax
19323     3d/compare-eax-and 0/imm32/false
19324     75/jump-if-!= $maybe-define-var:end/disp8
19325     # otherwise update vars
19326     (push *(ebp+0x10) *(ebp+8))
19327     (push *(ebp+0x10) *(ebp+0xc))
19328     (push *(ebp+0x10) 0)  # 'out' is always a fn output; never spill it
19329 $maybe-define-var:end:
19330     # . restore registers
19331     58/pop-to-eax
19332     # . epilogue
19333     89/<- %esp 5/r32/ebp
19334     5d/pop-to-ebp
19335     c3/return
19336 
19337 # simpler version of lookup-var-helper
19338 binding-exists?:  # target: (addr var), vars: (addr stack live-var) -> result/eax: boolean
19339     # pseudocode:
19340     #   var curr: (addr handle var) = &vars->data[vars->top - 12]
19341     #   var min = vars->data
19342     #   while curr >= min
19343     #     var v: (handle var) = *curr
19344     #     if v->name == target->name
19345     #       return true
19346     #     curr -= 12
19347     #   return false
19348     #
19349     # . prologue
19350     55/push-ebp
19351     89/<- %ebp 4/r32/esp
19352     # . save registers
19353     51/push-ecx
19354     52/push-edx
19355     56/push-esi
19356     # var target-name/ecx: (addr array byte) = lookup(target->name)
19357     8b/-> *(ebp+8) 0/r32/eax
19358     (lookup *eax *(eax+4))  # Var-name Var-name => eax
19359     89/<- %ecx 0/r32/eax
19360     # esi = vars
19361     8b/-> *(ebp+0xc) 6/r32/esi
19362     # eax = vars->top
19363     8b/-> *esi 0/r32/eax
19364     # var min/edx: (addr handle var) = vars->data
19365     8d/copy-address *(esi+8) 2/r32/edx
19366     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
19367     8d/copy-address *(esi+eax-4) 6/r32/esi  # vars + 8 + vars->type - 12
19368     {
19369 $binding-exists?:loop:
19370       # if (curr < min) return
19371       39/compare %esi 2/r32/edx
19372       0f 82/jump-if-addr< break/disp32
19373       # var v/eax: (addr var) = lookup(*curr)
19374       (lookup *esi *(esi+4))  # => eax
19375       # var vn/eax: (addr array byte) = lookup(v->name)
19376       (lookup *eax *(eax+4))  # Var-name Var-name => eax
19377       # if (vn == target-name) return true
19378       (string-equal? %ecx %eax)  # => eax
19379       3d/compare-eax-and 0/imm32/false
19380       75/jump-if-!= $binding-exists?:end/disp8  # eax already contains true
19381       # curr -= 12
19382       81 5/subop/subtract %esi 0xc/imm32
19383       e9/jump loop/disp32
19384     }
19385     b8/copy-to-eax 0/imm32/false
19386 $binding-exists?:end:
19387     # . restore registers
19388     5e/pop-to-esi
19389     5a/pop-to-edx
19390     59/pop-to-ecx
19391     # . epilogue
19392     89/<- %esp 5/r32/ebp
19393     5d/pop-to-ebp
19394     c3/return
19395 
19396 test-parse-mu-stmt:
19397     # . prologue
19398     55/push-ebp
19399     89/<- %ebp 4/r32/esp
19400     # setup
19401     8b/-> *Primitive-type-ids 0/r32/eax
19402     89/<- *Type-id 0/r32/eax  # stream-write
19403     (clear-stream _test-input-stream)
19404     (write _test-input-stream "increment n\n")
19405     # var vars/ecx: (stack (addr var) 16)
19406     81 5/subop/subtract %esp 0xc0/imm32
19407     68/push 0xc0/imm32/size
19408     68/push 0/imm32/top
19409     89/<- %ecx 4/r32/esp
19410     (clear-stack %ecx)
19411     # var v/edx: (handle var)
19412     68/push 0/imm32
19413     68/push 0/imm32
19414     89/<- %edx 4/r32/esp
19415     # var s/eax: (handle array byte)
19416     68/push 0/imm32
19417     68/push 0/imm32
19418     89/<- %eax 4/r32/esp
19419     # v = new var("n")
19420     (copy-array Heap "n" %eax)
19421     (new-var Heap *eax *(eax+4) %edx)
19422     #
19423     (push %ecx *edx)
19424     (push %ecx *(edx+4))
19425     (push %ecx 0)
19426     # var out/eax: (handle stmt)
19427     68/push 0/imm32
19428     68/push 0/imm32
19429     89/<- %eax 4/r32/esp
19430     # convert
19431     (parse-mu-stmt _test-input-stream %ecx 0 %eax Stderr 0)
19432     # var out-addr/edx: (addr stmt) = lookup(*out)
19433     (lookup *eax *(eax+4))  # => eax
19434     89/<- %edx 0/r32/eax
19435     # out->tag
19436     (check-ints-equal *edx 1 "F - test-parse-mu-stmt/tag")  # Stmt-tag is Stmt1
19437     # out->operation
19438     (lookup *(edx+4) *(edx+8))  # Stmt1-operation Stmt1-operation => eax
19439     (check-strings-equal %eax "increment" "F - test-parse-mu-stmt/name")  # Stmt1-operation
19440     # out->inouts->value->name
19441     # . eax = out->inouts
19442     (lookup *(edx+0xc) *(edx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
19443     # . eax = out->inouts->value
19444     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
19445     # . eax = out->inouts->value->name
19446     (lookup *eax *(eax+4))  # Var-name Var-name => eax
19447     # .
19448     (check-strings-equal %eax "n" "F - test-parse-mu-stmt/inout:0")
19449     # . epilogue
19450     89/<- %esp 5/r32/ebp
19451     5d/pop-to-ebp
19452     c3/return
19453 
19454 test-parse-mu-stmt-with-comma:
19455     # . prologue
19456     55/push-ebp
19457     89/<- %ebp 4/r32/esp
19458     # setup
19459     8b/-> *Primitive-type-ids 0/r32/eax
19460     89/<- *Type-id 0/r32/eax  # stream-write
19461     (clear-stream _test-input-stream)
19462     (write _test-input-stream "copy-to n, 3\n")
19463     # var vars/ecx: (stack (addr var) 16)
19464     81 5/subop/subtract %esp 0xc0/imm32
19465     68/push 0xc0/imm32/size
19466     68/push 0/imm32/top
19467     89/<- %ecx 4/r32/esp
19468     (clear-stack %ecx)
19469     # var v/edx: (handle var)
19470     68/push 0/imm32
19471     68/push 0/imm32
19472     89/<- %edx 4/r32/esp
19473     # var s/eax: (handle array byte)
19474     68/push 0/imm32
19475     68/push 0/imm32
19476     89/<- %eax 4/r32/esp
19477     # v = new var("n")
19478     (copy-array Heap "n" %eax)
19479     (new-var Heap *eax *(eax+4) %edx)
19480     #
19481     (push %ecx *edx)
19482     (push %ecx *(edx+4))
19483     (push %ecx 0)
19484     # var out/eax: (handle stmt)
19485     68/push 0/imm32
19486     68/push 0/imm32
19487     89/<- %eax 4/r32/esp
19488     # convert
19489     (parse-mu-stmt _test-input-stream %ecx 0 %eax Stderr 0)
19490     # var out-addr/edx: (addr stmt) = lookup(*out)
19491     (lookup *eax *(eax+4))  # => eax
19492     89/<- %edx 0/r32/eax
19493     # out->tag
19494     (check-ints-equal *edx 1 "F - test-parse-mu-stmt-with-comma/tag")  # Stmt-tag is Stmt1
19495     # out->operation
19496     (lookup *(edx+4) *(edx+8))  # Stmt1-operation Stmt1-operation => eax
19497     (check-strings-equal %eax "copy-to" "F - test-parse-mu-stmt-with-comma/name")  # Stmt1-operation
19498     # out->inouts->value->name
19499     # . eax = out->inouts
19500     (lookup *(edx+0xc) *(edx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
19501     # . eax = out->inouts->value
19502     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
19503     # . eax = out->inouts->value->name
19504     (lookup *eax *(eax+4))  # Var-name Var-name => eax
19505     # .
19506     (check-strings-equal %eax "n" "F - test-parse-mu-stmt-with-comma/inout:0")
19507     # . epilogue
19508     89/<- %esp 5/r32/ebp
19509     5d/pop-to-ebp
19510     c3/return
19511 
19512 new-var:  # ad: (addr allocation-descriptor), name: (handle array byte), out: (addr handle var)
19513     # . prologue
19514     55/push-ebp
19515     89/<- %ebp 4/r32/esp
19516     # . save registers
19517     50/push-eax
19518     51/push-ecx
19519     # ecx = out
19520     8b/-> *(ebp+0x14) 1/r32/ecx
19521     #
19522     (allocate *(ebp+8) *Var-size %ecx)
19523     # var out-addr/eax: (addr var)
19524     (lookup *ecx *(ecx+4))  # => eax
19525     # out-addr->name = name
19526     8b/-> *(ebp+0xc) 1/r32/ecx
19527     89/<- *eax 1/r32/ecx  # Var-name
19528     8b/-> *(ebp+0x10) 1/r32/ecx
19529     89/<- *(eax+4) 1/r32/ecx  # Var-name
19530 #?     (write-buffered Stderr "var ")
19531 #?     (lookup *(ebp+0xc) *(ebp+0x10))
19532 #?     (write-buffered Stderr %eax)
19533 #?     (write-buffered Stderr " at ")
19534 #?     8b/-> *(ebp+0x14) 1/r32/ecx
19535 #?     (lookup *ecx *(ecx+4))  # => eax
19536 #?     (write-int32-hex-buffered Stderr %eax)
19537 #?     (write-buffered Stderr Newline)
19538 #?     (flush Stderr)
19539 $new-var:end:
19540     # . restore registers
19541     59/pop-to-ecx
19542     58/pop-to-eax
19543     # . epilogue
19544     89/<- %esp 5/r32/ebp
19545     5d/pop-to-ebp
19546     c3/return
19547 
19548 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)
19549     # . prologue
19550     55/push-ebp
19551     89/<- %ebp 4/r32/esp
19552     # . save registers
19553     50/push-eax
19554     51/push-ecx
19555     # if (!is-hex-int?(name)) abort
19556     (is-hex-int? *(ebp+0xc))  # => eax
19557     3d/compare-eax-and 0/imm32/false
19558     0f 84/jump-if-= $new-literal-integer:abort/disp32
19559     # a little more error-checking
19560     (check-mu-hex-int *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
19561     # out = new var(s)
19562     (new-var-from-slice *(ebp+8) *(ebp+0xc) *(ebp+0x10))
19563     # var out-addr/ecx: (addr var) = lookup(*out)
19564     8b/-> *(ebp+0x10) 0/r32/eax
19565     (lookup *eax *(eax+4))  # => eax
19566     89/<- %ecx 0/r32/eax
19567     # out-addr->block-depth = *Curr-block-depth
19568     8b/-> *Curr-block-depth 0/r32/eax
19569     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
19570     # out-addr->type = new tree()
19571     8d/copy-address *(ecx+8) 0/r32/eax  # Var-type
19572     (allocate *(ebp+8) *Type-tree-size %eax)
19573     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
19574     c7 0/subop/copy *eax 1/imm32/true  # Type-tree-is-atom
19575     # nothing else to do; default type is 'literal'
19576 $new-literal-integer:end:
19577     # . reclaim locals
19578     81 0/subop/add %esp 8/imm32
19579     # . restore registers
19580     59/pop-to-ecx
19581     58/pop-to-eax
19582     # . epilogue
19583     89/<- %esp 5/r32/ebp
19584     5d/pop-to-ebp
19585     c3/return
19586 
19587 $new-literal-integer:abort:
19588     (write-buffered *(ebp+0x18) "fn ")
19589     8b/-> *(ebp+0x14) 0/r32/eax
19590     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19591     (write-buffered *(ebp+0x18) %eax)
19592     (write-buffered *(ebp+0x18) ": variable '")
19593     (write-slice-buffered *(ebp+0x18) *(ebp+0xc))
19594     (write-buffered *(ebp+0x18) "' cannot begin with a digit (or do you have a typo in a number?)\n")
19595     (flush *(ebp+0x18))
19596     (stop *(ebp+0x1c) 1)
19597     # never gets here
19598 
19599 # precondition: name is a valid hex integer; require a '0x' prefix
19600 check-mu-hex-int:  # name: (addr slice), err: (addr buffered-file), ed: (addr exit-descriptor)
19601     # . prologue
19602     55/push-ebp
19603     89/<- %ebp 4/r32/esp
19604     # . save registers
19605     50/push-eax
19606     51/push-ecx
19607     52/push-edx
19608     # ecx = name
19609     8b/-> *(ebp+8) 1/r32/ecx
19610     # var start/edx: (addr byte) = name->start
19611     8b/-> *ecx 2/r32/edx
19612     # if (*start == '-') ++start
19613     b8/copy-to-eax 0/imm32
19614     8a/copy-byte *edx 0/r32/AL
19615     3d/compare-eax-and 0x2d/imm32/dash
19616     {
19617       75/jump-if-!= break/disp8
19618       42/increment-edx
19619     }
19620     # var end/ecx: (addr byte) = name->end
19621     8b/-> *(ecx+4) 1/r32/ecx
19622     # var len/eax: int = name->end - name->start
19623     89/<- %eax 1/r32/ecx
19624     29/subtract-from %eax 2/r32/edx
19625     # if (len <= 1) return
19626     3d/compare-eax-with 1/imm32
19627     0f 8e/jump-if-<= $check-mu-hex-int:end/disp32
19628 $check-mu-hex-int:length->-1:
19629     # if slice-starts-with?({start, end}, "0x") return
19630     # . var tmp = {start, end}
19631     51/push-ecx
19632     52/push-edx
19633     89/<- %eax 4/r32/esp
19634     # .
19635     (slice-starts-with? %eax "0x")  # => eax
19636     # . reclaim tmp
19637     81 0/subop/add %esp 8/imm32
19638     # .
19639     3d/compare-eax-with 0/imm32/false
19640     75/jump-if-!= $check-mu-hex-int:end/disp8
19641 $check-mu-hex-int:abort:
19642     # otherwise abort
19643     (write-buffered *(ebp+0xc) "literal integers are always hex in Mu; start '")
19644     (write-slice-buffered *(ebp+0xc) *(ebp+8))
19645     (write-buffered *(ebp+0xc) "' with a '0x' to be unambiguous, converting it to hexadecimal as necessary.\n")
19646     (flush *(ebp+0xc))
19647     (stop *(ebp+0x10) 1)
19648 $check-mu-hex-int:end:
19649     # . restore registers
19650     5a/pop-to-edx
19651     59/pop-to-ecx
19652     58/pop-to-eax
19653     # . epilogue
19654     89/<- %esp 5/r32/ebp
19655     5d/pop-to-ebp
19656     c3/return
19657 
19658 new-literal:  # ad: (addr allocation-descriptor), name: (addr slice), out: (addr handle var)
19659     # . prologue
19660     55/push-ebp
19661     89/<- %ebp 4/r32/esp
19662     # . save registers
19663     50/push-eax
19664     51/push-ecx
19665     # var s/ecx: (handle array byte)
19666     68/push 0/imm32
19667     68/push 0/imm32
19668     89/<- %ecx 4/r32/esp
19669     # s = slice-to-string(name)
19670     (slice-to-string Heap *(ebp+0xc) %ecx)
19671     # allocate to out
19672     (new-var *(ebp+8) *ecx *(ecx+4) *(ebp+0x10))
19673     # var out-addr/ecx: (addr var) = lookup(*out)
19674     8b/-> *(ebp+0x10) 1/r32/ecx
19675     (lookup *ecx *(ecx+4))  # => eax
19676     89/<- %ecx 0/r32/eax
19677     # out-addr->block-depth = *Curr-block-depth
19678     8b/-> *Curr-block-depth 0/r32/eax
19679     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
19680     # out-addr->type/eax = new type
19681     8d/copy-address *(ecx+8) 0/r32/eax  # Var-type
19682     (allocate *(ebp+8) *Type-tree-size %eax)
19683     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
19684     # nothing else to do; default type is 'literal'
19685     c7 0/subop/copy *eax 1/imm32/true  # Type-tree-is-atom
19686 $new-literal:end:
19687     # . reclaim locals
19688     81 0/subop/add %esp 8/imm32
19689     # . restore registers
19690     59/pop-to-ecx
19691     58/pop-to-eax
19692     # . epilogue
19693     89/<- %esp 5/r32/ebp
19694     5d/pop-to-ebp
19695     c3/return
19696 
19697 new-literal-string:  # ad: (addr allocation-descriptor), name: (addr slice), out: (addr handle var)
19698     # . prologue
19699     55/push-ebp
19700     89/<- %ebp 4/r32/esp
19701     # . save registers
19702     50/push-eax
19703     51/push-ecx
19704     # var s/ecx: (handle array byte)
19705     68/push 0/imm32
19706     68/push 0/imm32
19707     89/<- %ecx 4/r32/esp
19708     # s = slice-to-string(name)
19709     (slice-to-string Heap *(ebp+0xc) %ecx)
19710     # allocate to out
19711     (new-var *(ebp+8) *ecx *(ecx+4) *(ebp+0x10))
19712     # var out-addr/ecx: (addr var) = lookup(*out)
19713     8b/-> *(ebp+0x10) 1/r32/ecx
19714     (lookup *ecx *(ecx+4))  # => eax
19715     89/<- %ecx 0/r32/eax
19716     # out-addr->block-depth = *Curr-block-depth
19717     8b/-> *Curr-block-depth 0/r32/eax
19718     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
19719     # out-addr->type/eax = new type
19720     8d/copy-address *(ecx+8) 0/r32/eax  # Var-type
19721     (allocate *(ebp+8) *Type-tree-size %eax)
19722     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
19723     # out-addr->type->value = literal-string
19724     c7 0/subop/copy *(eax+4) 0x10/imm32/type-id-string-literal  # Type-tree-value
19725     # out-addr->type->is-atom? = true
19726     c7 0/subop/copy *eax 1/imm32/true  # Type-tree-is-atom
19727 $new-literal-string:end:
19728     # . reclaim locals
19729     81 0/subop/add %esp 8/imm32
19730     # . restore registers
19731     59/pop-to-ecx
19732     58/pop-to-eax
19733     # . epilogue
19734     89/<- %esp 5/r32/ebp
19735     5d/pop-to-ebp
19736     c3/return
19737 
19738 new-var-from-slice:  # ad: (addr allocation-descriptor), name: (addr slice), out: (addr handle var)
19739     # . prologue
19740     55/push-ebp
19741     89/<- %ebp 4/r32/esp
19742     # . save registers
19743     51/push-ecx
19744     # var tmp/ecx: (handle array byte)
19745     68/push 0/imm32
19746     68/push 0/imm32
19747     89/<- %ecx 4/r32/esp
19748     # tmp = slice-to-string(name)
19749     (slice-to-string Heap *(ebp+0xc) %ecx)
19750     # out = new-var(tmp)
19751     (new-var *(ebp+8) *ecx *(ecx+4) *(ebp+0x10))
19752 $new-var-from-slice:end:
19753     # . reclaim locals
19754     81 0/subop/add %esp 8/imm32
19755     # . restore registers
19756     59/pop-to-ecx
19757     # . epilogue
19758     89/<- %esp 5/r32/ebp
19759     5d/pop-to-ebp
19760     c3/return
19761 
19762 new-var-def:  # ad: (addr allocation-descriptor), var: (handle var), out: (addr handle stmt)
19763     # . prologue
19764     55/push-ebp
19765     89/<- %ebp 4/r32/esp
19766     # . save registers
19767     50/push-eax
19768     51/push-ecx
19769     #
19770     (allocate *(ebp+8) *Stmt-size *(ebp+0x14))
19771     # var out-addr/eax: (addr stmt) = lookup(*out)
19772     8b/-> *(ebp+0x14) 0/r32/eax
19773     (lookup *eax *(eax+4))  # => eax
19774     # out-addr->tag = stmt
19775     c7 0/subop/copy *eax 2/imm32/tag/var-on-stack  # Stmt-tag
19776     # result->var = var
19777     8b/-> *(ebp+0xc) 1/r32/ecx
19778     89/<- *(eax+4) 1/r32/ecx  # Vardef-var
19779     8b/-> *(ebp+0x10) 1/r32/ecx
19780     89/<- *(eax+8) 1/r32/ecx  # Vardef-var
19781 $new-var-def:end:
19782     # . restore registers
19783     59/pop-to-ecx
19784     58/pop-to-eax
19785     # . epilogue
19786     89/<- %esp 5/r32/ebp
19787     5d/pop-to-ebp
19788     c3/return
19789 
19790 new-reg-var-def:  # ad: (addr allocation-descriptor), var: (handle var), out: (addr handle stmt)
19791     # . prologue
19792     55/push-ebp
19793     89/<- %ebp 4/r32/esp
19794     # . save registers
19795     50/push-eax
19796     # eax = out
19797     8b/-> *(ebp+0x14) 0/r32/eax
19798     #
19799     (allocate *(ebp+8) *Stmt-size %eax)
19800     # var out-addr/eax: (addr stmt) = lookup(*out)
19801     (lookup *eax *(eax+4))  # => eax
19802     # set tag
19803     c7 0/subop/copy *eax 3/imm32/tag/var-in-register  # Stmt-tag
19804     # set output
19805     8d/copy-address *(eax+0x14) 0/r32/eax  # Regvardef-outputs
19806     (append-stmt-var Heap  *(ebp+0xc) *(ebp+0x10)  0 0  0  %eax)
19807 $new-reg-var-def:end:
19808     # . restore registers
19809     58/pop-to-eax
19810     # . epilogue
19811     89/<- %esp 5/r32/ebp
19812     5d/pop-to-ebp
19813     c3/return
19814 
19815 append-list:  # ad: (addr allocation-descriptor), value: (handle _type), list: (handle list _type), out: (addr handle list _type)
19816     # . prologue
19817     55/push-ebp
19818     89/<- %ebp 4/r32/esp
19819     # . save registers
19820     50/push-eax
19821     51/push-ecx
19822     57/push-edi
19823     # edi = out
19824     8b/-> *(ebp+0x1c) 7/r32/edi
19825     # *out = new list
19826     (allocate *(ebp+8) *List-size %edi)
19827     # var out-addr/edi: (addr list _type) = lookup(*out)
19828     (lookup *edi *(edi+4))  # => eax
19829     89/<- %edi 0/r32/eax
19830     # out-addr->value = value
19831     8b/-> *(ebp+0xc) 0/r32/eax
19832     89/<- *edi 0/r32/eax  # List-value
19833     8b/-> *(ebp+0x10) 0/r32/eax
19834     89/<- *(edi+4) 0/r32/eax  # List-value
19835     # if (list == null) return
19836     81 7/subop/compare *(ebp+0x14) 0/imm32
19837     74/jump-if-= $append-list:end/disp8
19838     # otherwise append
19839 $append-list:non-empty-list:
19840     # var curr/eax: (addr list _type) = lookup(list)
19841     (lookup *(ebp+0x14) *(ebp+0x18))  # => eax
19842     # while (curr->next != null) curr = curr->next
19843     {
19844       81 7/subop/compare *(eax+8) 0/imm32  # List-next
19845       74/jump-if-= break/disp8
19846       # curr = lookup(curr->next)
19847       (lookup *(eax+8) *(eax+0xc))  # List-next, List-next => eax
19848       #
19849       eb/jump loop/disp8
19850     }
19851     # edi = out
19852     8b/-> *(ebp+0x1c) 7/r32/edi
19853     # curr->next = out
19854     8b/-> *edi 1/r32/ecx
19855     89/<- *(eax+8) 1/r32/ecx  # List-next
19856     8b/-> *(edi+4) 1/r32/ecx
19857     89/<- *(eax+0xc) 1/r32/ecx  # List-next
19858     # out = list
19859     8b/-> *(ebp+0x14) 1/r32/ecx
19860     89/<- *edi 1/r32/ecx
19861     8b/-> *(ebp+0x18) 1/r32/ecx
19862     89/<- *(edi+4) 1/r32/ecx
19863 $append-list:end:
19864     # . restore registers
19865     5f/pop-to-edi
19866     59/pop-to-ecx
19867     58/pop-to-eax
19868     # . epilogue
19869     89/<- %esp 5/r32/ebp
19870     5d/pop-to-ebp
19871     c3/return
19872 
19873 append-stmt-var:  # ad: (addr allocation-descriptor), v: (handle var), vars: (handle stmt-var), is-deref?: boolean, out: (addr handle stmt-var)
19874     # . prologue
19875     55/push-ebp
19876     89/<- %ebp 4/r32/esp
19877     # . save registers
19878     50/push-eax
19879     51/push-ecx
19880     57/push-edi
19881     # edi = out
19882     8b/-> *(ebp+0x20) 7/r32/edi
19883     # out = new stmt-var
19884     (allocate *(ebp+8) *Stmt-var-size %edi)
19885     # var out-addr/ecx: (addr stmt-var) = lookup(*out)
19886     (lookup *edi *(edi+4))  # => eax
19887     89/<- %ecx 0/r32/eax
19888     # out-addr->value = v
19889     8b/-> *(ebp+0xc) 0/r32/eax
19890     89/<- *ecx 0/r32/eax  # Stmt-var-value
19891     8b/-> *(ebp+0x10) 0/r32/eax
19892     89/<- *(ecx+4) 0/r32/eax  # Stmt-var-value
19893     # out-addr->is-deref? = is-deref?
19894     8b/-> *(ebp+0x1c) 0/r32/eax
19895     89/<- *(ecx+0x10) 0/r32/eax  # Stmt-var-is-deref
19896     # if (vars == null) return result
19897     81 7/subop/compare *(ebp+0x14) 0/imm32/null
19898     74/jump-if-= $append-stmt-var:end/disp8
19899     # otherwise append
19900     # var curr/eax: (addr stmt-var) = lookup(vars)
19901     (lookup *(ebp+0x14) *(ebp+0x18))  # => eax
19902     # while (curr->next != null) curr = curr->next
19903     {
19904       81 7/subop/compare *(eax+8) 0/imm32  # Stmt-var-next
19905       74/jump-if-= break/disp8
19906       # curr = lookup(curr->next)
19907       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next, Stmt-var-next => eax
19908       #
19909       eb/jump loop/disp8
19910     }
19911     # curr->next = out
19912     8b/-> *edi 1/r32/ecx
19913     89/<- *(eax+8) 1/r32/ecx  # Stmt-var-next
19914     8b/-> *(edi+4) 1/r32/ecx
19915     89/<- *(eax+0xc) 1/r32/ecx  # Stmt-var-next
19916     # out = vars
19917     8b/-> *(ebp+0x14) 1/r32/ecx
19918     89/<- *edi 1/r32/ecx
19919     8b/-> *(ebp+0x18) 1/r32/ecx
19920     89/<- *(edi+4) 1/r32/ecx
19921 $append-stmt-var:end:
19922     # . restore registers
19923     5f/pop-to-edi
19924     59/pop-to-ecx
19925     58/pop-to-eax
19926     # . epilogue
19927     89/<- %esp 5/r32/ebp
19928     5d/pop-to-ebp
19929     c3/return
19930 
19931 append-to-block:  # ad: (addr allocation-descriptor), block: (addr block), x: (handle stmt)
19932     # . prologue
19933     55/push-ebp
19934     89/<- %ebp 4/r32/esp
19935     # . save registers
19936     50/push-eax
19937     56/push-esi
19938     # esi = block
19939     8b/-> *(ebp+0xc) 6/r32/esi
19940     # block->stmts = append(x, block->stmts)
19941     8d/copy-address *(esi+4) 0/r32/eax  # Block-stmts
19942     (append-list *(ebp+8)  *(ebp+0x10) *(ebp+0x14)  *(esi+4) *(esi+8)  %eax)  # ad, x, x, Block-stmts, Block-stmts
19943 $append-to-block:end:
19944     # . restore registers
19945     5e/pop-to-esi
19946     58/pop-to-eax
19947     # . epilogue
19948     89/<- %esp 5/r32/ebp
19949     5d/pop-to-ebp
19950     c3/return
19951 
19952 ## Parsing types
19953 # We need to create metadata on user-defined types, and we need to use this
19954 # metadata as we parse instructions.
19955 # However, we also want to allow types to be used before their definitions.
19956 # This means we can't ever assume any type data structures exist.
19957 
19958 lookup-or-create-constant:  # container: (addr stmt-var), field-name: (addr slice), out: (addr handle var)
19959     # . prologue
19960     55/push-ebp
19961     89/<- %ebp 4/r32/esp
19962     # . save registers
19963     50/push-eax
19964     56/push-esi
19965     # var container-type/esi: type-id
19966     (container-type *(ebp+8))  # => eax
19967     89/<- %esi 0/r32/eax
19968     # var tmp/eax: (handle typeinfo) = find-or-create-typeinfo(container-type)
19969     68/push 0/imm32
19970     68/push 0/imm32
19971     89/<- %eax 4/r32/esp
19972     (find-or-create-typeinfo %esi %eax)
19973     # var tmp-addr/eax: (addr typeinfo) = lookup(tmp)
19974     (lookup *eax *(eax+4))  # => eax
19975     # result = find-or-create-typeinfo-output-var(typeinfo, field-name)
19976 #?     (write-buffered Stderr "constant: ")
19977 #?     (write-slice-buffered Stderr *(ebp+0xc))
19978 #?     (write-buffered Stderr Newline)
19979 #?     (flush Stderr)
19980     (find-or-create-typeinfo-output-var %eax *(ebp+0xc) *(ebp+0x10))
19981 #?     8b/-> *(ebp+0x10) 0/r32/eax
19982 #?     (write-buffered Stderr "@")
19983 #?     (lookup *eax *(eax+4))
19984 #?     (write-int32-hex-buffered Stderr %eax)
19985 #?     (lookup *eax *(eax+4))
19986 #?     (write-buffered Stderr %eax)
19987 #?     (write-buffered Stderr Newline)
19988 #?     (flush Stderr)
19989 #?     (write-buffered Stderr "offset: ")
19990 #?     8b/-> *(eax+0x14) 0/r32/eax
19991 #?     (write-int32-hex-buffered Stderr %eax)
19992 #?     (write-buffered Stderr Newline)
19993 #?     (flush Stderr)
19994 $lookup-or-create-constant:end:
19995     # . reclaim locals
19996     81 0/subop/add %esp 8/imm32
19997     # . restore registers
19998     5e/pop-to-esi
19999     58/pop-to-eax
20000     # . epilogue
20001     89/<- %esp 5/r32/ebp
20002     5d/pop-to-ebp
20003     c3/return
20004 
20005 # if addr var:
20006 #   container->var->type->right->left->value
20007 # otherwise
20008 #   container->var->type->value
20009 container-type:  # container: (addr stmt-var) -> result/eax: type-id
20010     # . prologue
20011     55/push-ebp
20012     89/<- %ebp 4/r32/esp
20013     #
20014     8b/-> *(ebp+8) 0/r32/eax
20015     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
20016     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20017     {
20018       81 7/subop/compare *(eax+8) 0/imm32  # Type-tree-right
20019       74/jump-if-= break/disp8
20020       (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
20021       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
20022     }
20023     8b/-> *(eax+4) 0/r32/eax  # Type-tree-value
20024 $container-type:end:
20025     # . epilogue
20026     89/<- %esp 5/r32/ebp
20027     5d/pop-to-ebp
20028     c3/return
20029 
20030 is-container?:  # t: type-id -> result/eax: boolean
20031     # . prologue
20032     55/push-ebp
20033     89/<- %ebp 4/r32/esp
20034     #
20035     8b/-> *(ebp+8) 0/r32/eax
20036     c1/shift 4/subop/left %eax 2/imm8
20037     3b/compare 0/r32/eax *Primitive-type-ids
20038     0f 9d/set-if->= %al
20039     81 4/subop/and %eax 0xff/imm32
20040 $is-container?:end:
20041     # . epilogue
20042     89/<- %esp 5/r32/ebp
20043     5d/pop-to-ebp
20044     c3/return
20045 
20046 find-or-create-typeinfo:  # t: type-id, out: (addr handle typeinfo)
20047     # . prologue
20048     55/push-ebp
20049     89/<- %ebp 4/r32/esp
20050     # . save registers
20051     50/push-eax
20052     51/push-ecx
20053     52/push-edx
20054     57/push-edi
20055     # edi = out
20056     8b/-> *(ebp+0xc) 7/r32/edi
20057     # var fields/ecx: (handle table (handle array byte) (handle typeinfo-entry))
20058     68/push 0/imm32
20059     68/push 0/imm32
20060     89/<- %ecx 4/r32/esp
20061     # find-typeinfo(t, out)
20062     (find-typeinfo *(ebp+8) %edi)
20063     {
20064       # if (*out != 0) break
20065       81 7/subop/compare *edi 0/imm32
20066       0f 85/jump-if-!= break/disp32
20067 $find-or-create-typeinfo:create:
20068       # *out = allocate
20069       (allocate Heap *Typeinfo-size %edi)
20070       # var tmp/eax: (addr typeinfo) = lookup(*out)
20071       (lookup *edi *(edi+4))  # => eax
20072 #?     (write-buffered Stderr "created typeinfo at ")
20073 #?     (write-int32-hex-buffered Stderr %eax)
20074 #?     (write-buffered Stderr " for type-id ")
20075 #?     (write-int32-hex-buffered Stderr *(ebp+8))
20076 #?     (write-buffered Stderr Newline)
20077 #?     (flush Stderr)
20078       # tmp->id = t
20079       8b/-> *(ebp+8) 2/r32/edx
20080       89/<- *eax 2/r32/edx  # Typeinfo-id
20081       # tmp->fields = new table
20082       # . fields = new table
20083       (new-stream Heap 0x40 *Typeinfo-fields-row-size %ecx)
20084       # . tmp->fields = fields
20085       8b/-> *ecx 2/r32/edx
20086       89/<- *(eax+4) 2/r32/edx  # Typeinfo-fields
20087       8b/-> *(ecx+4) 2/r32/edx
20088       89/<- *(eax+8) 2/r32/edx  # Typeinfo-fields
20089       # tmp->next = Program->types
20090       8b/-> *_Program-types 1/r32/ecx
20091       89/<- *(eax+0x10) 1/r32/ecx  # Typeinfo-next
20092       8b/-> *_Program-types->payload 1/r32/ecx
20093       89/<- *(eax+0x14) 1/r32/ecx  # Typeinfo-next
20094       # Program->types = out
20095       8b/-> *edi 1/r32/ecx
20096       89/<- *_Program-types 1/r32/ecx
20097       8b/-> *(edi+4) 1/r32/ecx
20098       89/<- *_Program-types->payload 1/r32/ecx
20099     }
20100 $find-or-create-typeinfo:end:
20101     # . reclaim locals
20102     81 0/subop/add %esp 8/imm32
20103     # . restore registers
20104     5f/pop-to-edi
20105     5a/pop-to-edx
20106     59/pop-to-ecx
20107     58/pop-to-eax
20108     # . epilogue
20109     89/<- %esp 5/r32/ebp
20110     5d/pop-to-ebp
20111     c3/return
20112 
20113 find-typeinfo:  # t: type-id, out: (addr handle typeinfo)
20114     # . prologue
20115     55/push-ebp
20116     89/<- %ebp 4/r32/esp
20117     # . save registers
20118     50/push-eax
20119     51/push-ecx
20120     52/push-edx
20121     57/push-edi
20122     # ecx = t
20123     8b/-> *(ebp+8) 1/r32/ecx
20124     # edi = out
20125     8b/-> *(ebp+0xc) 7/r32/edi
20126     # *out = Program->types
20127     8b/-> *_Program-types 0/r32/eax
20128     89/<- *edi 0/r32/eax
20129     8b/-> *_Program-types->payload 0/r32/eax
20130     89/<- *(edi+4) 0/r32/eax
20131     {
20132 $find-typeinfo:loop:
20133       # if (*out == 0) break
20134       81 7/subop/compare *edi 0/imm32
20135       74/jump-if-= break/disp8
20136 $find-typeinfo:check:
20137       # var tmp/eax: (addr typeinfo) = lookup(*out)
20138       (lookup *edi *(edi+4))  # => eax
20139       # if (tmp->id == t) break
20140       39/compare *eax 1/r32/ecx  # Typeinfo-id
20141       74/jump-if-= break/disp8
20142 $find-typeinfo:continue:
20143       # *out = tmp->next
20144       8b/-> *(eax+0x10) 2/r32/edx  # Typeinfo-next
20145       89/<- *edi 2/r32/edx
20146       8b/-> *(eax+0x14) 2/r32/edx  # Typeinfo-next
20147       89/<- *(edi+4) 2/r32/edx
20148       #
20149       eb/jump loop/disp8
20150     }
20151 $find-typeinfo:end:
20152     # . restore registers
20153     5f/pop-to-edi
20154     5a/pop-to-edx
20155     59/pop-to-ecx
20156     58/pop-to-eax
20157     # . epilogue
20158     89/<- %esp 5/r32/ebp
20159     5d/pop-to-ebp
20160     c3/return
20161 
20162 find-or-create-typeinfo-output-var:  # T: (addr typeinfo), f: (addr slice), out: (addr handle var)
20163     # . prologue
20164     55/push-ebp
20165     89/<- %ebp 4/r32/esp
20166     # . save registers
20167     50/push-eax
20168     52/push-edx
20169     57/push-edi
20170     # var dest/edi: (handle typeinfo-entry)
20171     68/push 0/imm32
20172     68/push 0/imm32
20173     89/<- %edi 4/r32/esp
20174     # find-or-create-typeinfo-fields(T, f, dest)
20175     (find-or-create-typeinfo-fields *(ebp+8) *(ebp+0xc) %edi)
20176     # var dest-addr/edi: (addr typeinfo-entry) = lookup(dest)
20177     (lookup *edi *(edi+4))  # => eax
20178     89/<- %edi 0/r32/eax
20179     # if dest-addr->output-var doesn't exist, create it
20180     {
20181       81 7/subop/compare *(edi+0xc) 0/imm32  # Typeinfo-entry-output-var
20182       0f 85/jump-if-!= break/disp32
20183       # dest-addr->output-var = new var(dummy name, type, -1 offset)
20184       # . var name/eax: (handle array byte) = "field"
20185       68/push 0/imm32
20186       68/push 0/imm32
20187       89/<- %eax 4/r32/esp
20188       (slice-to-string Heap *(ebp+0xc) %eax)
20189       # . new var
20190       8d/copy-address *(edi+0xc) 2/r32/edx
20191       (new-var Heap  *eax *(eax+4)  %edx)
20192       # . reclaim name
20193       81 0/subop/add %esp 8/imm32
20194       # var result/edx: (addr var) = lookup(dest-addr->output-var)
20195       (lookup *(edi+0xc) *(edi+0x10))  # => eax
20196       89/<- %edx 0/r32/eax
20197       # result->type = new constant type
20198       8d/copy-address *(edx+8) 0/r32/eax  # Var-type
20199       (allocate Heap *Type-tree-size %eax)
20200       (lookup *(edx+8) *(edx+0xc))  # => eax
20201       c7 0/subop/copy *eax 1/imm32/true  # Type-tree-is-atom
20202       c7 0/subop/copy *(eax+4) 6/imm32/constant  # Type-tree-value
20203       c7 0/subop/copy *(eax+8) 0/imm32  # Type-tree-left
20204       c7 0/subop/copy *(eax+0xc) 0/imm32  # Type-tree-right
20205       c7 0/subop/copy *(eax+0x10) 0/imm32  # Type-tree-right
20206       # result->offset isn't filled out yet
20207       c7 0/subop/copy *(edx+0x14) -1/imm32/uninitialized  # Var-offset
20208     }
20209     # out = dest-addr->output-var
20210     8b/-> *(ebp+0x10) 2/r32/edx
20211     8b/-> *(edi+0xc) 0/r32/eax  # Typeinfo-entry-output-var
20212     89/<- *edx 0/r32/eax
20213     8b/-> *(edi+0x10) 0/r32/eax  # Typeinfo-entry-output-var
20214     89/<- *(edx+4) 0/r32/eax
20215 $find-or-create-typeinfo-output-var:end:
20216     # . reclaim locals
20217     81 0/subop/add %esp 8/imm32
20218     # . restore registers
20219     5f/pop-to-edi
20220     5a/pop-to-edx
20221     58/pop-to-eax
20222     # . epilogue
20223     89/<- %esp 5/r32/ebp
20224     5d/pop-to-ebp
20225     c3/return
20226 
20227 find-or-create-typeinfo-fields:  # T: (addr typeinfo), f: (addr slice), out: (addr handle typeinfo-entry)
20228     # . prologue
20229     55/push-ebp
20230     89/<- %ebp 4/r32/esp
20231     # . save registers
20232     50/push-eax
20233     56/push-esi
20234     57/push-edi
20235     # eax = lookup(T->fields)
20236     8b/-> *(ebp+8) 0/r32/eax
20237     (lookup *(eax+4) *(eax+8))  # Typeinfo-fields Typeinfo-fields => eax
20238     # edi = out
20239     8b/-> *(ebp+0x10) 7/r32/edi
20240     # var src/esi: (addr handle typeinfo-entry) = get-or-insert-slice(T->fields, f)
20241     (get-or-insert-slice %eax *(ebp+0xc) *Typeinfo-fields-row-size Heap)  # => eax
20242     89/<- %esi 0/r32/eax
20243     # if src doesn't exist, allocate it
20244     {
20245       81 7/subop/compare *esi 0/imm32
20246       75/jump-if-!= break/disp8
20247       (allocate Heap *Typeinfo-entry-size %esi)
20248 #?       (write-buffered Stderr "handle at ")
20249 #?       (write-int32-hex-buffered Stderr %esi)
20250 #?       (write-buffered Stderr ": ")
20251 #?       (write-int32-hex-buffered Stderr *esi)
20252 #?       (write-buffered Stderr " ")
20253 #?       (write-int32-hex-buffered Stderr *(esi+4))
20254 #?       (write-buffered Stderr Newline)
20255 #?       (flush Stderr)
20256 #?       (lookup *esi *(esi+4))
20257 #?       (write-buffered Stderr "created typeinfo fields at ")
20258 #?       (write-int32-hex-buffered Stderr %esi)
20259 #?       (write-buffered Stderr " for ")
20260 #?       (write-int32-hex-buffered Stderr *(ebp+8))
20261 #?       (write-buffered Stderr Newline)
20262 #?       (flush Stderr)
20263     }
20264     # *out = src
20265     # . *edi = *src
20266     8b/-> *esi 0/r32/eax
20267     89/<- *edi 0/r32/eax
20268     8b/-> *(esi+4) 0/r32/eax
20269     89/<- *(edi+4) 0/r32/eax
20270 $find-or-create-typeinfo-fields:end:
20271     # . restore registers
20272     5f/pop-to-edi
20273     5e/pop-to-esi
20274     58/pop-to-eax
20275     # . epilogue
20276     89/<- %esp 5/r32/ebp
20277     5d/pop-to-ebp
20278     c3/return
20279 
20280 populate-mu-type:  # in: (addr stream byte), t: (addr typeinfo), err: (addr buffered-file), ed: (addr exit-descriptor)
20281     # pseudocode:
20282     #   var line: (stream byte 512)
20283     #   curr-index = 0
20284     #   while true
20285     #     clear-stream(line)
20286     #     read-line-buffered(in, line)
20287     #     if line->write == 0
20288     #       abort
20289     #     word-slice = next-mu-token(line)
20290     #     if slice-empty?(word-slice)               # end of line
20291     #       continue
20292     #     if slice-equal?(word-slice, "}")
20293     #       break
20294     #     var v: (handle var) = parse-var-with-type(word-slice, line)
20295     #     var r: (handle typeinfo-fields) = find-or-create-typeinfo-fields(t, word-slice/v->name)
20296     #     TODO: ensure that r->first is null
20297     #     r->index = curr-index
20298     #     curr-index++
20299     #     r->input-var = v
20300     #     if r->output-var == 0
20301     #       r->output-var = new literal
20302     #     TODO: ensure nothing else in line
20303     # t->total-size-in-bytes = -2 (not yet initialized)
20304     #
20305     # . prologue
20306     55/push-ebp
20307     89/<- %ebp 4/r32/esp
20308     # var curr-index: int at *(ebp-4)
20309     68/push 0/imm32
20310     # . save registers
20311     50/push-eax
20312     51/push-ecx
20313     52/push-edx
20314     53/push-ebx
20315     56/push-esi
20316     57/push-edi
20317     # edi = t
20318     8b/-> *(ebp+0xc) 7/r32/edi
20319     # var line/ecx: (stream byte 512)
20320     81 5/subop/subtract %esp 0x200/imm32
20321     68/push 0x200/imm32/size
20322     68/push 0/imm32/read
20323     68/push 0/imm32/write
20324     89/<- %ecx 4/r32/esp
20325     # var word-slice/edx: slice
20326     68/push 0/imm32/end
20327     68/push 0/imm32/start
20328     89/<- %edx 4/r32/esp
20329     # var v/esi: (handle var)
20330     68/push 0/imm32
20331     68/push 0/imm32
20332     89/<- %esi 4/r32/esp
20333     # var r/ebx: (handle typeinfo-entry)
20334     68/push 0/imm32
20335     68/push 0/imm32
20336     89/<- %ebx 4/r32/esp
20337     {
20338 $populate-mu-type:line-loop:
20339       (clear-stream %ecx)
20340       (read-line-buffered *(ebp+8) %ecx)
20341       # if (line->write == 0) abort
20342       81 7/subop/compare *ecx 0/imm32
20343       0f 84/jump-if-= $populate-mu-type:error1/disp32
20344 +--  6 lines: #?       # dump line ------------------------------------------------------------------------------------------------------------------------------------------------------
20350       (next-mu-token %ecx %edx)
20351       # if slice-empty?(word-slice) continue
20352       (slice-empty? %edx)  # => eax
20353       3d/compare-eax-and 0/imm32
20354       0f 85/jump-if-!= loop/disp32
20355       # if slice-equal?(word-slice, "}") break
20356       (slice-equal? %edx "}")
20357       3d/compare-eax-and 0/imm32
20358       0f 85/jump-if-!= break/disp32
20359 $populate-mu-type:parse-element:
20360       # v = parse-var-with-type(word-slice, first-line)
20361       # must do this first to strip the trailing ':' from word-slice before
20362       # using it in find-or-create-typeinfo-fields below
20363       # TODO: clean up that mutation in parse-var-with-type
20364       (type-name *edi)  # Typeinfo-id => eax
20365       (parse-var-with-type %edx %ecx %esi %eax *(ebp+0x10) *(ebp+0x14))
20366       # if v is an addr, abort
20367       (lookup *esi *(esi+4))  # => eax
20368       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20369       (is-mu-addr-type? %eax)  # => eax
20370       3d/compare-eax-and 0/imm32/false
20371       0f 85/jump-if-!= $populate-mu-type:error2/disp32
20372       # if v is an array, abort  (we could support it, but initialization gets complex)
20373       (lookup *esi *(esi+4))  # => eax
20374       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20375       (is-mu-array-type? %eax)  # => eax
20376       3d/compare-eax-and 0/imm32/false
20377       0f 85/jump-if-!= $populate-mu-type:error3/disp32
20378       # if v is a byte, abort
20379       (lookup *esi *(esi+4))  # => eax
20380       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20381       (is-simple-mu-type? %eax 8)  # byte => eax
20382       3d/compare-eax-and 0/imm32/false
20383       0f 85/jump-if-!= $populate-mu-type:error4/disp32
20384       # if v is a slice, abort
20385       (lookup *esi *(esi+4))  # => eax
20386       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20387       (is-simple-mu-type? %eax 0xc)  # slice => eax
20388       3d/compare-eax-and 0/imm32/false
20389       0f 85/jump-if-!= $populate-mu-type:error5/disp32
20390       # if v is a stream, abort  (we could support it, but initialization gets even more complex)
20391       (lookup *esi *(esi+4))  # => eax
20392       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20393       (is-mu-stream-type? %eax)  # => eax
20394       3d/compare-eax-and 0/imm32/false
20395       0f 85/jump-if-!= $populate-mu-type:error6/disp32
20396       # var tmp/ecx
20397       51/push-ecx
20398 $populate-mu-type:create-typeinfo-fields:
20399       # var r/ebx: (handle typeinfo-entry)
20400       (find-or-create-typeinfo-fields %edi %edx %ebx)
20401       # r->index = curr-index
20402       (lookup *ebx *(ebx+4))  # => eax
20403       8b/-> *(ebp-4) 1/r32/ecx
20404 #?       (write-buffered Stderr "saving index ")
20405 #?       (write-int32-hex-buffered Stderr %ecx)
20406 #?       (write-buffered Stderr " at ")
20407 #?       (write-int32-hex-buffered Stderr %edi)
20408 #?       (write-buffered Stderr Newline)
20409 #?       (flush Stderr)
20410       89/<- *(eax+8) 1/r32/ecx  # Typeinfo-entry-index
20411       # ++curr-index
20412       ff 0/subop/increment *(ebp-4)
20413 $populate-mu-type:set-input-type:
20414       # r->input-var = v
20415       8b/-> *esi 1/r32/ecx
20416       89/<- *eax 1/r32/ecx  # Typeinfo-entry-input-var
20417       8b/-> *(esi+4) 1/r32/ecx
20418       89/<- *(eax+4) 1/r32/ecx  # Typeinfo-entry-input-var
20419       # restore line
20420       59/pop-to-ecx
20421       {
20422 $populate-mu-type:create-output-type:
20423         # if (r->output-var == 0) create a new var with some placeholder data
20424         81 7/subop/compare *(eax+0xc) 0/imm32  # Typeinfo-entry-output-var
20425         75/jump-if-!= break/disp8
20426         8d/copy-address *(eax+0xc) 0/r32/eax  # Typeinfo-entry-output-var
20427         (new-literal Heap %edx %eax)
20428       }
20429       e9/jump loop/disp32
20430     }
20431 $populate-mu-type:invalidate-total-size-in-bytes:
20432     # Offsets and total size may not be accurate here since we may not yet
20433     # have encountered the element types.
20434     # We'll recompute them separately after parsing the entire program.
20435     c7 0/subop/copy *(edi+0xc) -2/imm32/uninitialized  # Typeinfo-total-size-in-bytes
20436 $populate-mu-type:end:
20437     # . reclaim locals
20438     81 0/subop/add %esp 0x224/imm32
20439     # . restore registers
20440     5f/pop-to-edi
20441     5e/pop-to-esi
20442     5b/pop-to-ebx
20443     5a/pop-to-edx
20444     59/pop-to-ecx
20445     58/pop-to-eax
20446     # reclaim curr-index
20447     81 0/subop/add %esp 4/imm32
20448     # . epilogue
20449     89/<- %esp 5/r32/ebp
20450     5d/pop-to-ebp
20451     c3/return
20452 
20453 $populate-mu-type:error1:
20454     # error("incomplete type definition '" t->name "'\n")
20455     (write-buffered *(ebp+0x10) "incomplete type definition '")
20456     (type-name *edi)  # Typeinfo-id => eax
20457     (write-buffered *(ebp+0x10) %eax)
20458     (write-buffered *(ebp+0x10) "\n")
20459     (flush *(ebp+0x10))
20460     (stop *(ebp+0x14) 1)
20461     # never gets here
20462 
20463 $populate-mu-type:error2:
20464     (write-buffered *(ebp+0x10) "type ")
20465     (type-name *edi)  # Typeinfo-id => eax
20466     (write-buffered *(ebp+0x10) %eax)
20467     (write-buffered *(ebp+0x10) ": 'addr' elements not allowed\n")
20468     (flush *(ebp+0x10))
20469     (stop *(ebp+0x14) 1)
20470     # never gets here
20471 
20472 $populate-mu-type:error3:
20473     (write-buffered *(ebp+0x10) "type ")
20474     (type-name *edi)  # Typeinfo-id => eax
20475     (write-buffered *(ebp+0x10) %eax)
20476     (write-buffered *(ebp+0x10) ": 'array' elements not allowed for now\n")
20477     (flush *(ebp+0x10))
20478     (stop *(ebp+0x14) 1)
20479     # never gets here
20480 
20481 $populate-mu-type:error4:
20482     (write-buffered *(ebp+0x10) "type ")
20483     (type-name *edi)  # Typeinfo-id => eax
20484     (write-buffered *(ebp+0x10) %eax)
20485     (write-buffered *(ebp+0x10) ": 'byte' elements not allowed\n")
20486     (flush *(ebp+0x10))
20487     (stop *(ebp+0x14) 1)
20488     # never gets here
20489 
20490 $populate-mu-type:error5:
20491     (write-buffered *(ebp+0x10) "type ")
20492     (type-name *edi)  # Typeinfo-id => eax
20493     (write-buffered *(ebp+0x10) %eax)
20494     (write-buffered *(ebp+0x10) ": 'slice' elements not allowed\n")
20495     (flush *(ebp+0x10))
20496     (stop *(ebp+0x14) 1)
20497     # never gets here
20498 
20499 $populate-mu-type:error6:
20500     (write-buffered *(ebp+0x10) "type ")
20501     (type-name *edi)  # Typeinfo-id => eax
20502     (write-buffered *(ebp+0x10) %eax)
20503     (write-buffered *(ebp+0x10) ": 'stream' elements not allowed for now\n")
20504     (flush *(ebp+0x10))
20505     (stop *(ebp+0x14) 1)
20506     # never gets here
20507 
20508 type-name:  # index: int -> result/eax: (addr array byte)
20509     # . prologue
20510     55/push-ebp
20511     89/<- %ebp 4/r32/esp
20512     #
20513     (index Type-id *(ebp+8))
20514 $type-name:end:
20515     # . epilogue
20516     89/<- %esp 5/r32/ebp
20517     5d/pop-to-ebp
20518     c3/return
20519 
20520 index:  # arr: (addr stream (handle array byte)), index: int -> result/eax: (addr array byte)
20521     # . prologue
20522     55/push-ebp
20523     89/<- %ebp 4/r32/esp
20524     # . save registers
20525     56/push-esi
20526     # TODO: bounds-check index
20527     # esi = arr
20528     8b/-> *(ebp+8) 6/r32/esi
20529     # eax = index
20530     8b/-> *(ebp+0xc) 0/r32/eax
20531     # eax = *(arr + 12 + index)
20532     8b/-> *(esi+eax<<2+0xc) 0/r32/eax
20533 $index:end:
20534     # . restore registers
20535     5e/pop-to-esi
20536     # . epilogue
20537     89/<- %esp 5/r32/ebp
20538     5d/pop-to-ebp
20539     c3/return
20540 
20541 #######################################################
20542 # Compute type sizes
20543 #######################################################
20544 
20545 # Compute the sizes of all user-defined types.
20546 # We'll need the sizes of their elements, which may be other user-defined
20547 # types, which we will compute as needed.
20548 
20549 # Initially, all user-defined types have their sizes set to -2 (invalid)
20550 populate-mu-type-sizes:  # err: (addr buffered-file), ed: (addr exit-descriptor)
20551     # . prologue
20552     55/push-ebp
20553     89/<- %ebp 4/r32/esp
20554 $populate-mu-type-sizes:total-sizes:
20555     # var curr/eax: (addr typeinfo) = lookup(Program->types)
20556     (lookup *_Program-types *_Program-types->payload)  # => eax
20557     {
20558       # if (curr == null) break
20559       3d/compare-eax-and 0/imm32/null
20560       74/jump-if-= break/disp8
20561       (populate-mu-type-sizes-in-type %eax *(ebp+8) *(ebp+0xc))
20562       # curr = lookup(curr->next)
20563       (lookup *(eax+0x10) *(eax+0x14))  # Typeinfo-next Typeinfo-next => eax
20564       eb/jump loop/disp8
20565     }
20566 $populate-mu-type-sizes:offsets:
20567     # curr = *Program->types
20568     (lookup *_Program-types *_Program-types->payload)  # => eax
20569     {
20570       # if (curr == null) break
20571       3d/compare-eax-and 0/imm32/null
20572       74/jump-if-= break/disp8
20573       (populate-mu-type-offsets %eax *(ebp+8) *(ebp+0xc))
20574       # curr = curr->next
20575       (lookup *(eax+0x10) *(eax+0x14))  # Typeinfo-next Typeinfo-next => eax
20576       eb/jump loop/disp8
20577     }
20578 $populate-mu-type-sizes:end:
20579     # . epilogue
20580     89/<- %esp 5/r32/ebp
20581     5d/pop-to-ebp
20582     c3/return
20583 
20584 # compute sizes of all fields, recursing as necessary
20585 # sum up all their sizes to arrive at total size
20586 # fields may be out of order, but that doesn't affect the answer
20587 populate-mu-type-sizes-in-type:  # T: (addr typeinfo), err: (addr buffered-file), ed: (addr exit-descriptor)
20588     # . prologue
20589     55/push-ebp
20590     89/<- %ebp 4/r32/esp
20591     # . save registers
20592     50/push-eax
20593     51/push-ecx
20594     52/push-edx
20595     56/push-esi
20596     57/push-edi
20597     # esi = T
20598     8b/-> *(ebp+8) 6/r32/esi
20599     # if T is already computed, return
20600     81 7/subop/compare *(esi+0xc) 0/imm32  # Typeinfo-total-size-in-bytes
20601     0f 8d/jump-if->= $populate-mu-type-sizes-in-type:end/disp32
20602     # if T is being computed, abort
20603     81 7/subop/compare *(esi+0xc) -1/imm32/being-computed  # Typeinfo-total-size-in-bytes
20604     0f 84/jump-if-= $populate-mu-type-sizes-in-type:abort/disp32
20605     # tag T (-2 to -1) to avoid infinite recursion
20606     c7 0/subop/copy *(esi+0xc) -1/imm32/being-computed  # Typeinfo-total-size-in-bytes
20607     # var total-size/edi: int = 0
20608     bf/copy-to-edi 0/imm32
20609     # - for every field, if it's a user-defined type, compute its size
20610     # var table/ecx: (addr table (handle array byte) (handle typeinfo-entry)) = lookup(T->fields)
20611     (lookup *(esi+4) *(esi+8))  # Typeinfo-fields Typeinfo-fields => eax
20612     89/<- %ecx 0/r32/eax
20613     # var table-size/edx: int = table->write
20614     8b/-> *ecx 2/r32/edx  # stream-write
20615     # var curr/ecx: (addr table_row) = table->data
20616     8d/copy-address *(ecx+0xc) 1/r32/ecx
20617     # var max/edx: (addr table_row) = table->data + table->write
20618     8d/copy-address *(ecx+edx) 2/r32/edx
20619     {
20620 $populate-mu-type-sizes-in-type:loop:
20621       # if (curr >= max) break
20622       39/compare %ecx 2/r32/edx
20623       73/jump-if-addr>= break/disp8
20624       # var t/eax: (addr typeinfo-entry) = lookup(curr->value)
20625       (lookup *(ecx+8) *(ecx+0xc))  # => eax
20626       # if (t->input-var == 0) silently ignore it; we'll emit a nice error message while type-checking
20627       81 7/subop/compare *eax 0/imm32  # Typeinfo-entry-input-var
20628       74/jump-if-= $populate-mu-type-sizes-in-type:end/disp8
20629       # compute size of t->input-var
20630       (lookup *eax *(eax+4))  # Typeinfo-entry-input-var Typeinfo-entry-input-var => eax
20631       (compute-size-of-var %eax *(ebp+0xc) *(ebp+0x10))  # => eax
20632       # result += eax
20633       01/add-to %edi 0/r32/eax
20634       # curr += row-size
20635       81 0/subop/add %ecx 0x10/imm32  # Typeinfo-fields-row-size
20636       #
20637       eb/jump loop/disp8
20638     }
20639     # - save result
20640     89/<- *(esi+0xc) 7/r32/edi  # Typeinfo-total-size-in-bytes
20641 $populate-mu-type-sizes-in-type:end:
20642     # . restore registers
20643     5f/pop-to-edi
20644     5e/pop-to-esi
20645     5a/pop-to-edx
20646     59/pop-to-ecx
20647     58/pop-to-eax
20648     # . epilogue
20649     89/<- %esp 5/r32/ebp
20650     5d/pop-to-ebp
20651     c3/return
20652 
20653 $populate-mu-type-sizes-in-type:abort:
20654     (write-buffered *(ebp+0xc) "cycle in type definitions\n")
20655     (flush *(ebp+0xc))
20656     (stop *(ebp+0x10) 1)
20657     # never gets here
20658 
20659 # Analogous to size-of, except we need to compute what size-of can just read
20660 # off the right data structures.
20661 compute-size-of-var:  # in: (addr var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
20662     # . prologue
20663     55/push-ebp
20664     89/<- %ebp 4/r32/esp
20665     # . push registers
20666     51/push-ecx
20667     # var t/ecx: (addr type-tree) = lookup(v->type)
20668     8b/-> *(ebp+8) 1/r32/ecx
20669     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
20670     89/<- %ecx 0/r32/eax
20671     # if (t->is-atom == false) t = lookup(t->left)
20672     {
20673       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
20674       75/jump-if-!= break/disp8
20675       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
20676       89/<- %ecx 0/r32/eax
20677     }
20678     # TODO: ensure t is an atom
20679     (compute-size-of-type-id *(ecx+4) *(ebp+0xc) *(ebp+0x10))  # Type-tree-value => eax
20680 $compute-size-of-var:end:
20681     # . restore registers
20682     59/pop-to-ecx
20683     # . epilogue
20684     89/<- %esp 5/r32/ebp
20685     5d/pop-to-ebp
20686     c3/return
20687 
20688 compute-size-of-type-id:  # t: type-id, err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
20689     # . prologue
20690     55/push-ebp
20691     89/<- %ebp 4/r32/esp
20692     # . save registers
20693     51/push-ecx
20694     # var out/ecx: (handle typeinfo)
20695     68/push 0/imm32
20696     68/push 0/imm32
20697     89/<- %ecx 4/r32/esp
20698     # eax = t
20699     8b/-> *(ebp+8) 0/r32/eax
20700     # if t is a literal, return 0
20701     3d/compare-eax-and 0/imm32/literal
20702     0f 84/jump-if-= $compute-size-of-type-id:end/disp32  # eax changes type from type-id to int
20703     # if t is a byte, return 4 (because we don't really support non-multiples of 4)
20704     3d/compare-eax-and 8/imm32/byte
20705     {
20706       75/jump-if-!= break/disp8
20707       b8/copy-to-eax 4/imm32
20708       eb/jump $compute-size-of-type-id:end/disp8
20709     }
20710     # if t is a handle, return 8
20711     3d/compare-eax-and 4/imm32/handle
20712     {
20713       75/jump-if-!= break/disp8
20714       b8/copy-to-eax 8/imm32
20715       eb/jump $compute-size-of-type-id:end/disp8  # eax changes type from type-id to int
20716     }
20717     # if t is a slice, return 8
20718     3d/compare-eax-and 0xc/imm32/slice
20719     {
20720       75/jump-if-!= break/disp8
20721       b8/copy-to-eax 8/imm32
20722       eb/jump $compute-size-of-type-id:end/disp8  # eax changes type from type-id to int
20723     }
20724     # if t is a user-defined type, compute its size
20725     # TODO: support non-atom type
20726     (find-typeinfo %eax %ecx)
20727     {
20728       81 7/subop/compare *ecx 0/imm32
20729       74/jump-if-= break/disp8
20730 $compute-size-of-type-id:user-defined:
20731       (lookup *ecx *(ecx+4))  # => eax
20732       (populate-mu-type-sizes-in-type %eax *(ebp+0xc) *(ebp+0x10))
20733       8b/-> *(eax+0xc) 0/r32/eax  # Typeinfo-total-size-in-bytes
20734       eb/jump $compute-size-of-type-id:end/disp8
20735     }
20736     # otherwise return the word size
20737     b8/copy-to-eax 4/imm32
20738 $compute-size-of-type-id:end:
20739     # . reclaim locals
20740     81 0/subop/add %esp 8/imm32
20741     # . restore registers
20742     59/pop-to-ecx
20743     # . epilogue
20744     89/<- %esp 5/r32/ebp
20745     5d/pop-to-ebp
20746     c3/return
20747 
20748 # at this point we have total sizes for all user-defined types
20749 # compute offsets for each element
20750 # complication: fields may be out of order
20751 populate-mu-type-offsets:  # in: (addr typeinfo), err: (addr buffered-file), ed: (addr exit-descriptor)
20752     # . prologue
20753     55/push-ebp
20754     89/<- %ebp 4/r32/esp
20755     # . save registers
20756     50/push-eax
20757     51/push-ecx
20758     52/push-edx
20759     53/push-ebx
20760     56/push-esi
20761     57/push-edi
20762 #?     (dump-typeinfos "aaa\n")
20763     # var curr-offset/edi: int = 0
20764     bf/copy-to-edi 0/imm32
20765     # var table/ecx: (addr table string_key (handle typeinfo-entry)) = lookup(in->fields)
20766     8b/-> *(ebp+8) 1/r32/ecx
20767     (lookup *(ecx+4) *(ecx+8))  # Typeinfo-fields Typeinfo-fields => eax
20768     89/<- %ecx 0/r32/eax
20769     # var num-elems/edx: int = table->write / Typeinfo-fields-row-size
20770     8b/-> *ecx 2/r32/edx  # stream-write
20771     c1 5/subop/shift-right-logical  %edx 4/imm8
20772     # var i/ebx: int = 0
20773     bb/copy-to-ebx 0/imm32
20774     {
20775 $populate-mu-type-offsets:loop:
20776       39/compare %ebx 2/r32/edx
20777       0f 8d/jump-if->= break/disp32
20778 #?       (write-buffered Stderr "looking up index ")
20779 #?       (write-int32-hex-buffered Stderr %ebx)
20780 #?       (write-buffered Stderr " in ")
20781 #?       (write-int32-hex-buffered Stderr *(ebp+8))
20782 #?       (write-buffered Stderr Newline)
20783 #?       (flush Stderr)
20784       # var v/esi: (addr typeinfo-entry)
20785       (locate-typeinfo-entry-with-index %ecx %ebx *(ebp+0xc) *(ebp+0x10))  # => eax
20786       89/<- %esi 0/r32/eax
20787       # if v is null, silently move on; we'll emit a nice error message while type-checking
20788       81 7/subop/compare %esi 0/imm32  # Typeinfo-entry-input-var
20789       74/jump-if-= $populate-mu-type-offsets:end/disp8
20790       # if (v->input-var == 0) silently ignore v; we'll emit a nice error message while type-checking
20791       81 7/subop/compare *esi 0/imm32  # Typeinfo-entry-input-var
20792       74/jump-if-= $populate-mu-type-offsets:end/disp8
20793       # v->output-var->offset = curr-offset
20794       # . eax: (addr var)
20795       (lookup *(esi+0xc) *(esi+0x10))  # Typeinfo-entry-output-var Typeinfo-entry-output-var => eax
20796       89/<- *(eax+0x14) 7/r32/edi  # Var-offset
20797       # curr-offset += size-of(v->input-var)
20798       (lookup *esi *(esi+4))  # Typeinfo-entry-input-var Typeinfo-entry-input-var => eax
20799       (size-of %eax)  # => eax
20800       01/add-to %edi 0/r32/eax
20801       # ++i
20802       43/increment-ebx
20803       e9/jump loop/disp32
20804     }
20805 $populate-mu-type-offsets:end:
20806     # . restore registers
20807     5f/pop-to-edi
20808     5e/pop-to-esi
20809     5b/pop-to-ebx
20810     5a/pop-to-edx
20811     59/pop-to-ecx
20812     58/pop-to-eax
20813     # . epilogue
20814     89/<- %esp 5/r32/ebp
20815     5d/pop-to-ebp
20816     c3/return
20817 
20818 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)
20819     # . prologue
20820     55/push-ebp
20821     89/<- %ebp 4/r32/esp
20822     # . save registers
20823     51/push-ecx
20824     52/push-edx
20825     53/push-ebx
20826     56/push-esi
20827     57/push-edi
20828     # esi = table
20829     8b/-> *(ebp+8) 6/r32/esi
20830     # var curr/ecx: (addr row (handle array byte) (handle typeinfo-entry)) = table->data
20831     8d/copy-address *(esi+0xc) 1/r32/ecx
20832     # var max/edx: (addr byte) = &table->data[table->write]
20833     8b/-> *esi 2/r32/edx
20834     8d/copy-address *(ecx+edx) 2/r32/edx
20835     {
20836 $locate-typeinfo-entry-with-index:loop:
20837       39/compare %ecx 2/r32/edx
20838       73/jump-if-addr>= break/disp8
20839       # var v/eax: (addr typeinfo-entry)
20840       (lookup *(ecx+8) *(ecx+0xc))  # => eax
20841       # if (v->index == idx) return v
20842       8b/-> *(eax+8) 3/r32/ebx  # Typeinfo-entry-index
20843 #?       (write-buffered Stderr "comparing ")
20844 #?       (write-int32-hex-buffered Stderr %ebx)
20845 #?       (write-buffered Stderr " and ")
20846 #?       (write-int32-hex-buffered Stderr *(ebp+0xc))
20847 #?       (write-buffered Stderr Newline)
20848 #?       (flush Stderr)
20849       39/compare *(ebp+0xc) 3/r32/ebx
20850       74/jump-if-= $locate-typeinfo-entry-with-index:end/disp8
20851       # curr += Typeinfo-entry-size
20852       81 0/subop/add %ecx 0x10/imm32  # Typeinfo-entry-size
20853       #
20854       eb/jump loop/disp8
20855     }
20856     # return 0
20857     b8/copy-to-eax 0/imm32
20858 $locate-typeinfo-entry-with-index:end:
20859 #?     (write-buffered Stderr "returning ")
20860 #?     (write-int32-hex-buffered Stderr %eax)
20861 #?     (write-buffered Stderr Newline)
20862 #?     (flush Stderr)
20863     # . restore registers
20864     5f/pop-to-edi
20865     5e/pop-to-esi
20866     5b/pop-to-ebx
20867     5a/pop-to-edx
20868     59/pop-to-ecx
20869     # . epilogue
20870     89/<- %esp 5/r32/ebp
20871     5d/pop-to-ebp
20872     c3/return
20873 
20874 dump-typeinfos:  # hdr: (addr array byte)
20875     # . prologue
20876     55/push-ebp
20877     89/<- %ebp 4/r32/esp
20878     # . save registers
20879     50/push-eax
20880     #
20881     (write-buffered Stderr *(ebp+8))
20882     (flush Stderr)
20883     # var curr/eax: (addr typeinfo) = lookup(Program->types)
20884     (lookup *_Program-types *_Program-types->payload)  # => eax
20885     {
20886       # if (curr == null) break
20887       3d/compare-eax-and 0/imm32
20888       74/jump-if-= break/disp8
20889       (write-buffered Stderr "---\n")
20890       (flush Stderr)
20891       (dump-typeinfo %eax)
20892       # curr = lookup(curr->next)
20893       (lookup *(eax+0x10) *(eax+0x14))  # Typeinfo-next Typeinfo-next => eax
20894       eb/jump loop/disp8
20895     }
20896 $dump-typeinfos:end:
20897     # . restore registers
20898     58/pop-to-eax
20899     # . epilogue
20900     89/<- %esp 5/r32/ebp
20901     5d/pop-to-ebp
20902     c3/return
20903 
20904 dump-typeinfo:  # in: (addr typeinfo)
20905     # . prologue
20906     55/push-ebp
20907     89/<- %ebp 4/r32/esp
20908     # . save registers
20909     50/push-eax
20910     51/push-ecx
20911     52/push-edx
20912     53/push-ebx
20913     56/push-esi
20914     57/push-edi
20915     # esi = in
20916     8b/-> *(ebp+8) 6/r32/esi
20917     # var table/ecx: (addr table (handle array byte) (handle typeinfo-entry)) = lookup(T->fields)
20918     (lookup *(esi+4) *(esi+8))  # Typeinfo-fields Typeinfo-fields => eax
20919     89/<- %ecx 0/r32/eax
20920     (write-buffered Stderr "id:")
20921     (write-int32-hex-buffered Stderr *esi)
20922     (write-buffered Stderr "\n")
20923     (write-buffered Stderr "fields @ ")
20924     (write-int32-hex-buffered Stderr %ecx)
20925     (write-buffered Stderr Newline)
20926     (flush Stderr)
20927     (write-buffered Stderr "  write: ")
20928     (write-int32-hex-buffered Stderr *ecx)
20929     (write-buffered Stderr Newline)
20930     (flush Stderr)
20931     (write-buffered Stderr "  read: ")
20932     (write-int32-hex-buffered Stderr *(ecx+4))
20933     (write-buffered Stderr Newline)
20934     (flush Stderr)
20935     (write-buffered Stderr "  size: ")
20936     (write-int32-hex-buffered Stderr *(ecx+8))
20937     (write-buffered Stderr Newline)
20938     (flush Stderr)
20939     # var table-size/edx: int = table->write
20940     8b/-> *ecx 2/r32/edx  # stream-write
20941     # var curr/ecx: (addr table_row) = table->data
20942     8d/copy-address *(ecx+0xc) 1/r32/ecx
20943     # var max/edx: (addr table_row) = table->data + table->write
20944     8d/copy-address *(ecx+edx) 2/r32/edx
20945     {
20946 $dump-typeinfo:loop:
20947       # if (curr >= max) break
20948       39/compare %ecx 2/r32/edx
20949       0f 83/jump-if-addr>= break/disp32
20950       (write-buffered Stderr "  row:\n")
20951       (write-buffered Stderr "    key: ")
20952       (write-int32-hex-buffered Stderr *ecx)
20953       (write-buffered Stderr ",")
20954       (write-int32-hex-buffered Stderr *(ecx+4))
20955       (write-buffered Stderr " = '")
20956       (lookup *ecx *(ecx+4))
20957       (write-buffered Stderr %eax)
20958       (write-buffered Stderr "' @ ")
20959       (write-int32-hex-buffered Stderr %eax)
20960       (write-buffered Stderr Newline)
20961       (flush Stderr)
20962       (write-buffered Stderr "    value: ")
20963       (write-int32-hex-buffered Stderr *(ecx+8))
20964       (write-buffered Stderr ",")
20965       (write-int32-hex-buffered Stderr *(ecx+0xc))
20966       (write-buffered Stderr " = typeinfo-entry@")
20967       (lookup *(ecx+8) *(ecx+0xc))
20968       (write-int32-hex-buffered Stderr %eax)
20969       (write-buffered Stderr Newline)
20970       (flush Stderr)
20971       (write-buffered Stderr "        input var@")
20972       (dump-var 5 %eax)
20973       (lookup *(ecx+8) *(ecx+0xc))
20974       (write-buffered Stderr "        index: ")
20975       (write-int32-hex-buffered Stderr *(eax+8))
20976       (write-buffered Stderr Newline)
20977       (flush Stderr)
20978       (write-buffered Stderr "        output var@")
20979       8d/copy-address *(eax+0xc) 0/r32/eax  # Typeinfo-entry-output-var
20980       (dump-var 5 %eax)
20981       (flush Stderr)
20982       # curr += row-size
20983       81 0/subop/add %ecx 0x10/imm32  # Typeinfo-fields-row-size
20984       #
20985       e9/jump loop/disp32
20986     }
20987 $dump-typeinfo:end:
20988     # . restore registers
20989     5f/pop-to-edi
20990     5e/pop-to-esi
20991     5b/pop-to-ebx
20992     5a/pop-to-edx
20993     59/pop-to-ecx
20994     58/pop-to-eax
20995     # . epilogue
20996     89/<- %esp 5/r32/ebp
20997     5d/pop-to-ebp
20998     c3/return
20999 
21000 dump-var:  # indent: int, v: (addr handle var)
21001     # . prologue
21002     55/push-ebp
21003     89/<- %ebp 4/r32/esp
21004     # . save registers
21005     50/push-eax
21006     53/push-ebx
21007     # eax = v
21008     8b/-> *(ebp+0xc) 0/r32/eax
21009     #
21010     (write-int32-hex-buffered Stderr *eax)
21011     (write-buffered Stderr ",")
21012     (write-int32-hex-buffered Stderr *(eax+4))
21013     (write-buffered Stderr "->")
21014     (lookup *eax *(eax+4))
21015     (write-int32-hex-buffered Stderr %eax)
21016     (write-buffered Stderr Newline)
21017     (flush Stderr)
21018     {
21019       3d/compare-eax-and 0/imm32
21020       0f 84/jump-if-= break/disp32
21021       (emit-indent Stderr *(ebp+8))
21022       (write-buffered Stderr "name: ")
21023       89/<- %ebx 0/r32/eax
21024       (write-int32-hex-buffered Stderr *ebx)  # Var-name
21025       (write-buffered Stderr ",")
21026       (write-int32-hex-buffered Stderr *(ebx+4))  # Var-name
21027       (write-buffered Stderr "->")
21028       (lookup *ebx *(ebx+4))  # Var-name
21029       (write-int32-hex-buffered Stderr %eax)
21030       {
21031         3d/compare-eax-and 0/imm32
21032         74/jump-if-= break/disp8
21033         (write-buffered Stderr Space)
21034         (write-buffered Stderr %eax)
21035       }
21036       (write-buffered Stderr Newline)
21037       (flush Stderr)
21038       (emit-indent Stderr *(ebp+8))
21039       (write-buffered Stderr "block depth: ")
21040       (write-int32-hex-buffered Stderr *(ebx+0x10))  # Var-block-depth
21041       (write-buffered Stderr Newline)
21042       (flush Stderr)
21043       (emit-indent Stderr *(ebp+8))
21044       (write-buffered Stderr "stack offset: ")
21045       (write-int32-hex-buffered Stderr *(ebx+0x14))  # Var-offset
21046       (write-buffered Stderr Newline)
21047       (flush Stderr)
21048       (emit-indent Stderr *(ebp+8))
21049       (write-buffered Stderr "reg: ")
21050       (write-int32-hex-buffered Stderr *(ebx+0x18))  # Var-register
21051       (write-buffered Stderr ",")
21052       (write-int32-hex-buffered Stderr *(ebx+0x1c))  # Var-register
21053       (write-buffered Stderr "->")
21054       (flush Stderr)
21055       (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register
21056       (write-int32-hex-buffered Stderr %eax)
21057       {
21058         3d/compare-eax-and 0/imm32
21059         74/jump-if-= break/disp8
21060         (write-buffered Stderr Space)
21061         (write-buffered Stderr %eax)
21062       }
21063       (write-buffered Stderr Newline)
21064       (flush Stderr)
21065     }
21066 $dump-var:end:
21067     # . restore registers
21068     5b/pop-to-ebx
21069     58/pop-to-eax
21070     # . epilogue
21071     89/<- %esp 5/r32/ebp
21072     5d/pop-to-ebp
21073     c3/return
21074 
21075 #######################################################
21076 # Type-checking
21077 #######################################################
21078 
21079 check-mu-types:  # err: (addr buffered-file), ed: (addr exit-descriptor)
21080     # . prologue
21081     55/push-ebp
21082     89/<- %ebp 4/r32/esp
21083     # . save registers
21084     50/push-eax
21085     # var curr/eax: (addr function) = lookup(Program->functions)
21086     (lookup *_Program-functions *_Program-functions->payload)  # => eax
21087     {
21088 $check-mu-types:loop:
21089       # if (curr == null) break
21090       3d/compare-eax-and 0/imm32
21091       0f 84/jump-if-= break/disp32
21092 +--  8 lines: #?       # dump curr->name ------------------------------------------------------------------------------------------------------------------------------------------------
21100       (check-mu-function %eax *(ebp+8) *(ebp+0xc))
21101       # curr = lookup(curr->next)
21102       (lookup *(eax+0x20) *(eax+0x24))  # Function-next Function-next => eax
21103       e9/jump loop/disp32
21104     }
21105 $check-mu-types:end:
21106     # . restore registers
21107     58/pop-to-eax
21108     # . epilogue
21109     89/<- %esp 5/r32/ebp
21110     5d/pop-to-ebp
21111     c3/return
21112 
21113 check-mu-function:  # fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21114     # . prologue
21115     55/push-ebp
21116     89/<- %ebp 4/r32/esp
21117     # . save registers
21118     50/push-eax
21119     56/push-esi
21120     # esi = f
21121     8b/-> *(ebp+8) 6/r32/esi
21122     # outputs
21123     (lookup *(esi+0x10) *(esi+0x14))  # Function-outputs Function-outputs => eax
21124     (check-all-unique-registers %eax %esi *(ebp+0xc) *(ebp+0x10))
21125     # body
21126     (lookup *(esi+0x18) *(esi+0x1c))  # Function-body Function-body => eax
21127     (check-mu-block %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10))
21128     # if function has no outputs, we're done
21129     81 7/subop/compare *(esi+0x10) 0/imm32
21130     74/jump-if-= $check-mu-function:end/disp8
21131     # some final checks on body
21132     (check-final-stmt-is-return %eax %esi *(ebp+0xc) *(ebp+0x10))
21133     (check-no-breaks %eax %esi *(ebp+0xc) *(ebp+0x10))
21134 $check-mu-function:end:
21135     # . restore registers
21136     5e/pop-to-esi
21137     58/pop-to-eax
21138     # . epilogue
21139     89/<- %esp 5/r32/ebp
21140     5d/pop-to-ebp
21141     c3/return
21142 
21143 check-mu-block:  # block: (addr block), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21144     # . prologue
21145     55/push-ebp
21146     89/<- %ebp 4/r32/esp
21147     # . save registers
21148     50/push-eax
21149     # eax = block
21150     8b/-> *(ebp+8) 0/r32/eax
21151     # var stmts/eax: (addr list stmt) = lookup(block->statements)
21152     (lookup *(eax+4) *(eax+8))  # Block-stmts Block-stmts => eax
21153     #
21154     {
21155 $check-mu-block:check-empty:
21156       3d/compare-eax-and 0/imm32
21157       0f 84/jump-if-= break/disp32
21158       # emit block->statements
21159       (check-mu-stmt-list %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21160     }
21161 $check-mu-block:end:
21162     # . restore registers
21163     58/pop-to-eax
21164     # . epilogue
21165     89/<- %esp 5/r32/ebp
21166     5d/pop-to-ebp
21167     c3/return
21168 
21169 check-mu-stmt-list:  # stmts: (addr list stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21170     # . prologue
21171     55/push-ebp
21172     89/<- %ebp 4/r32/esp
21173     # . save registers
21174     50/push-eax
21175     56/push-esi
21176     # esi = stmts
21177     8b/-> *(ebp+8) 6/r32/esi
21178     {
21179 $check-mu-stmt-list:loop:
21180       81 7/subop/compare %esi 0/imm32
21181       0f 84/jump-if-= break/disp32
21182       # var curr-stmt/eax: (addr stmt) = lookup(stmts->value)
21183       (lookup *esi *(esi+4))  # List-value List-value => eax
21184       {
21185 $check-mu-stmt-list:check-for-block:
21186         81 7/subop/compare *eax 0/imm32/block  # Stmt-tag
21187         75/jump-if-!= break/disp8
21188 $check-mu-stmt-list:block:
21189         (check-mu-block %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21190         eb/jump $check-mu-stmt-list:continue/disp8
21191       }
21192       {
21193 $check-mu-stmt-list:check-for-stmt1:
21194         81 7/subop/compare *eax 1/imm32/stmt1  # Stmt-tag
21195         0f 85/jump-if-!= break/disp32
21196 $check-mu-stmt-list:stmt1:
21197         (check-mu-stmt %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21198         eb/jump $check-mu-stmt-list:continue/disp8
21199       }
21200       {
21201 $check-mu-stmt-list:check-for-reg-var-def:
21202         81 7/subop/compare *eax 3/imm32/reg-var-def  # Stmt-tag
21203         0f 85/jump-if-!= break/disp32
21204 $check-mu-stmt-list:reg-var-def:
21205         (check-mu-stmt %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21206         eb/jump $check-mu-stmt-list:continue/disp8
21207       }
21208 $check-mu-stmt-list:continue:
21209       # TODO: raise an error on unrecognized Stmt-tag
21210       (lookup *(esi+8) *(esi+0xc))  # List-next List-next => eax
21211       89/<- %esi 0/r32/eax
21212       e9/jump loop/disp32
21213     }
21214 $check-mu-stmt-list:end:
21215     # . restore registers
21216     5e/pop-to-esi
21217     58/pop-to-eax
21218     # . epilogue
21219     89/<- %esp 5/r32/ebp
21220     5d/pop-to-ebp
21221     c3/return
21222 
21223 check-mu-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21224     # . prologue
21225     55/push-ebp
21226     89/<- %ebp 4/r32/esp
21227     # . save registers
21228     50/push-eax
21229     # - if stmt's operation matches a primitive, check against it
21230     (has-primitive-name? *(ebp+8))  # => eax
21231     3d/compare-eax-and 0/imm32/false
21232     {
21233       74/jump-if-= break/disp8
21234       (check-mu-primitive *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21235       e9/jump $check-mu-stmt:end/disp32
21236     }
21237     # - otherwise find a function to check against
21238     # var f/eax: (addr function) = lookup(*Program->functions)
21239     (lookup *_Program-functions *_Program-functions->payload)  # => eax
21240     (find-matching-function %eax *(ebp+8))  # => eax
21241     3d/compare-eax-and 0/imm32
21242     {
21243       74/jump-if-= break/disp8
21244       (check-mu-call *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21245       eb/jump $check-mu-stmt:end/disp8
21246     }
21247     # var f/eax: (addr function) = lookup(*Program->signatures)
21248     (lookup *_Program-signatures *_Program-signatures->payload)  # => eax
21249     (find-matching-function %eax *(ebp+8))  # => eax
21250     3d/compare-eax-and 0/imm32
21251     {
21252       74/jump-if-= break/disp8
21253       (check-mu-call *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21254       eb/jump $check-mu-stmt:end/disp8
21255     }
21256     # - otherwise abort
21257     e9/jump $check-mu-stmt:unknown-call/disp32
21258 $check-mu-stmt:end:
21259     # . restore registers
21260     58/pop-to-eax
21261     # . epilogue
21262     89/<- %esp 5/r32/ebp
21263     5d/pop-to-ebp
21264     c3/return
21265 
21266 $check-mu-stmt:unknown-call:
21267     (write-buffered *(ebp+0x10) "unknown function '")
21268     8b/-> *(ebp+8) 0/r32/eax
21269     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
21270     (write-buffered *(ebp+0x10) %eax)
21271     (write-buffered *(ebp+0x10) "'\n")
21272     (flush *(ebp+0x10))
21273     (stop *(ebp+0x14) 1)
21274     # never gets here
21275 
21276 has-primitive-name?:  # stmt: (addr stmt) -> result/eax: boolean
21277     # . prologue
21278     55/push-ebp
21279     89/<- %ebp 4/r32/esp
21280     # . save registers
21281     51/push-ecx
21282     56/push-esi
21283     # var name/esi: (addr array byte) = lookup(stmt->operation)
21284     8b/-> *(ebp+8) 6/r32/esi
21285     (lookup *(esi+4) *(esi+8))  # Stmt1-operation Stmt1-operation => eax
21286     89/<- %esi 0/r32/eax
21287     # if (name == "return") return true
21288     (string-equal? %esi "return")  # => eax
21289     3d/compare-eax-and 0/imm32/false
21290     0f 85/jump-if-!= $has-primitive-name?:end/disp32
21291     # if (name == "get") return true
21292     (string-equal? %esi "get")  # => eax
21293     3d/compare-eax-and 0/imm32/false
21294     0f 85/jump-if-!= $has-primitive-name?:end/disp32
21295     # if (name == "index") return true
21296     (string-equal? %esi "index")  # => eax
21297     3d/compare-eax-and 0/imm32/false
21298     0f 85/jump-if-!= $has-primitive-name?:end/disp32
21299     # if (name == "length") return true
21300     (string-equal? %esi "length")  # => eax
21301     3d/compare-eax-and 0/imm32/false
21302     0f 85/jump-if-!= $has-primitive-name?:end/disp32
21303     # if (name == "compute-offset") return true
21304     (string-equal? %esi "compute-offset")  # => eax
21305     3d/compare-eax-and 0/imm32/false
21306     0f 85/jump-if-!= $has-primitive-name?:end/disp32
21307     # if (name == "copy-object") return true
21308     (string-equal? %esi "copy-object")  # => eax
21309     3d/compare-eax-and 0/imm32/false
21310     0f 85/jump-if-!= $has-primitive-name?:end/disp32
21311     # if (name == "clear-object") return true
21312     (string-equal? %esi "clear-object")  # => eax
21313     3d/compare-eax-and 0/imm32/false
21314     0f 85/jump-if-!= $has-primitive-name?:end/disp32
21315     # if (name == "allocate") return true
21316     (string-equal? %esi "allocate")  # => eax
21317     3d/compare-eax-and 0/imm32/false
21318     0f 85/jump-if-!= $has-primitive-name?:end/disp32
21319     # if (name == "populate") return true
21320     (string-equal? %esi "populate")  # => eax
21321     3d/compare-eax-and 0/imm32/false
21322     0f 85/jump-if-!= $has-primitive-name?:end/disp32
21323     # if (name == "populate-stream") return true
21324     (string-equal? %esi "populate-stream")  # => eax
21325     3d/compare-eax-and 0/imm32/false
21326     0f 85/jump-if-!= $has-primitive-name?:end/disp32
21327     # if (name == "read-from-stream") return true
21328     (string-equal? %esi "read-from-stream")  # => eax
21329     3d/compare-eax-and 0/imm32/false
21330     0f 85/jump-if-!= $has-primitive-name?:end/disp32
21331     # if (name == "write-to-stream") return true
21332     (string-equal? %esi "write-to-stream")  # => eax
21333     3d/compare-eax-and 0/imm32/false
21334     0f 85/jump-if-!= $has-primitive-name?:end/disp32
21335     # var curr/ecx: (addr primitive) = Primitives
21336     b9/copy-to-ecx Primitives/imm32
21337     {
21338 $has-primitive-name?:loop:
21339       # if (curr == null) break
21340       81 7/subop/compare %ecx 0/imm32
21341       74/jump-if-= break/disp8
21342       # if (primitive->name == name) return true
21343       (lookup *ecx *(ecx+4))  # Primitive-name Primitive-name => eax
21344 #?       (write-buffered Stderr %eax)
21345 #?       (write-buffered Stderr Newline)
21346 #?       (flush Stderr)
21347       (string-equal? %esi %eax)  # => eax
21348       3d/compare-eax-and 0/imm32/false
21349       75/jump-if-!= $has-primitive-name?:end/disp8
21350 $has-primitive-name?:next-primitive:
21351       # curr = curr->next
21352       (lookup *(ecx+0x3c) *(ecx+0x40))  # Primitive-next Primitive-next => eax
21353       89/<- %ecx 0/r32/eax
21354       #
21355       e9/jump loop/disp32
21356     }
21357     # return null
21358     b8/copy-to-eax 0/imm32
21359 $has-primitive-name?:end:
21360     # . restore registers
21361     5e/pop-to-esi
21362     59/pop-to-ecx
21363     # . epilogue
21364     89/<- %esp 5/r32/ebp
21365     5d/pop-to-ebp
21366     c3/return
21367 
21368 check-mu-primitive:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21369     # . prologue
21370     55/push-ebp
21371     89/<- %ebp 4/r32/esp
21372     # . save registers
21373     50/push-eax
21374     51/push-ecx
21375     # var op/ecx: (addr array byte) = lookup(stmt->operation)
21376     8b/-> *(ebp+8) 0/r32/eax
21377     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
21378     89/<- %ecx 0/r32/eax
21379     # if (op == "copy") check-mu-copy-stmt
21380     {
21381       (string-equal? %ecx "copy")  # => eax
21382       3d/compare-eax-and 0/imm32/false
21383       74/jump-if-= break/disp8
21384       (check-mu-copy-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21385       e9/jump $check-mu-primitive:end/disp32
21386     }
21387     # if (op == "copy-to") check-mu-copy-to-stmt
21388     {
21389       (string-equal? %ecx "copy-to")  # => eax
21390       3d/compare-eax-and 0/imm32/false
21391       74/jump-if-= break/disp8
21392       (check-mu-copy-to-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21393       e9/jump $check-mu-primitive:end/disp32
21394     }
21395     # if (op == "copy-byte") check-mu-copy-byte-stmt
21396     {
21397       (string-equal? %ecx "copy-byte")  # => eax
21398       3d/compare-eax-and 0/imm32/false
21399       74/jump-if-= break/disp8
21400       (check-mu-copy-byte-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21401       e9/jump $check-mu-primitive:end/disp32
21402     }
21403     # if (op == "copy-byte-to") check-mu-copy-byte-to-stmt
21404     {
21405       (string-equal? %ecx "copy-byte-to")  # => eax
21406       3d/compare-eax-and 0/imm32/false
21407       74/jump-if-= break/disp8
21408       (check-mu-copy-byte-to-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21409       e9/jump $check-mu-primitive:end/disp32
21410     }
21411     # if (op == "compare") check-mu-compare-stmt
21412     {
21413       (string-equal? %ecx "compare")  # => eax
21414       3d/compare-eax-and 0/imm32/false
21415       74/jump-if-= break/disp8
21416       (check-mu-compare-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21417       e9/jump $check-mu-primitive:end/disp32
21418     }
21419     # if (op == "address") check-mu-address-stmt
21420     {
21421       (string-equal? %ecx "address")  # => eax
21422       3d/compare-eax-and 0/imm32/false
21423       74/jump-if-= break/disp8
21424       (check-mu-address-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21425       e9/jump $check-mu-primitive:end/disp32
21426     }
21427     # if (op == "return") check-mu-return-stmt
21428     {
21429       (string-equal? %ecx "return")  # => eax
21430       3d/compare-eax-and 0/imm32/false
21431       74/jump-if-= break/disp8
21432       (check-mu-return-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21433       e9/jump $check-mu-primitive:end/disp32
21434     }
21435     # if (op == "get") check-mu-get-stmt
21436     {
21437       (string-equal? %ecx "get")  # => eax
21438       3d/compare-eax-and 0/imm32/false
21439       74/jump-if-= break/disp8
21440       (check-mu-get-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21441       e9/jump $check-mu-primitive:end/disp32
21442     }
21443     # if (op == "index") check-mu-index-stmt
21444     {
21445       (string-equal? %ecx "index")  # => eax
21446       3d/compare-eax-and 0/imm32/false
21447       74/jump-if-= break/disp8
21448       (check-mu-index-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21449       e9/jump $check-mu-primitive:end/disp32
21450     }
21451     # if (op == "length") check-mu-length-stmt
21452     {
21453       (string-equal? %ecx "length")  # => eax
21454       3d/compare-eax-and 0/imm32/false
21455       74/jump-if-= break/disp8
21456       (check-mu-length-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21457       e9/jump $check-mu-primitive:end/disp32
21458     }
21459     # if (op == "compute-offset") check-mu-compute-offset-stmt
21460     {
21461       (string-equal? %ecx "compute-offset")  # => eax
21462       3d/compare-eax-and 0/imm32/false
21463       74/jump-if-= break/disp8
21464       (check-mu-compute-offset-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21465       e9/jump $check-mu-primitive:end/disp32
21466     }
21467     # if (op == "copy-object") check-mu-copy-object-stmt
21468     {
21469       (string-equal? %ecx "copy-object")  # => eax
21470       3d/compare-eax-and 0/imm32/false
21471       74/jump-if-= break/disp8
21472       (check-mu-copy-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21473       e9/jump $check-mu-primitive:end/disp32
21474     }
21475     # if (op == "clear-object") check-mu-clear-object-stmt
21476     {
21477       (string-equal? %ecx "clear-object")  # => eax
21478       3d/compare-eax-and 0/imm32/false
21479       74/jump-if-= break/disp8
21480       (check-mu-clear-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21481       e9/jump $check-mu-primitive:end/disp32
21482     }
21483     # if (op == "allocate") check-mu-allocate-stmt
21484     {
21485       (string-equal? %ecx "allocate")  # => eax
21486       3d/compare-eax-and 0/imm32/false
21487       74/jump-if-= break/disp8
21488       (check-mu-allocate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21489       e9/jump $check-mu-primitive:end/disp32
21490     }
21491     # if (op == "populate") check-mu-populate-stmt
21492     {
21493       (string-equal? %ecx "populate")  # => eax
21494       3d/compare-eax-and 0/imm32/false
21495       74/jump-if-= break/disp8
21496       (check-mu-populate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21497       e9/jump $check-mu-primitive:end/disp32
21498     }
21499     # if (op == "populate-stream") check-mu-populate-stream-stmt
21500     {
21501       (string-equal? %ecx "populate-stream")  # => eax
21502       3d/compare-eax-and 0/imm32/false
21503       74/jump-if-= break/disp8
21504       (check-mu-populate-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21505       e9/jump $check-mu-primitive:end/disp32
21506     }
21507     # if (op == "read-from-stream") check-mu-read-from-stream-stmt
21508     {
21509       (string-equal? %ecx "read-from-stream")  # => eax
21510       3d/compare-eax-and 0/imm32/false
21511       74/jump-if-= break/disp8
21512       (check-mu-read-from-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21513       e9/jump $check-mu-primitive:end/disp32
21514     }
21515     # if (op == "write-to-stream") check-mu-write-to-stream-stmt
21516     {
21517       (string-equal? %ecx "write-to-stream")  # => eax
21518       3d/compare-eax-and 0/imm32/false
21519       74/jump-if-= break/disp8
21520       (check-mu-write-to-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21521       e9/jump $check-mu-primitive:end/disp32
21522     }
21523     # if (op == "convert") check-mu-convert-stmt
21524     {
21525       (string-equal? %ecx "convert")  # => eax
21526       3d/compare-eax-and 0/imm32/false
21527       74/jump-if-= break/disp8
21528       (check-mu-convert-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21529       e9/jump $check-mu-primitive:end/disp32
21530     }
21531     # otherwise check-numberlike-stmt
21532     (check-mu-numberlike-primitive *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21533 $check-mu-primitive:end:
21534     # . restore registers
21535     59/pop-to-ecx
21536     58/pop-to-eax
21537     # . epilogue
21538     89/<- %esp 5/r32/ebp
21539     5d/pop-to-ebp
21540     c3/return
21541 
21542 # by default, Mu primitives should only operate on 'number-like' types
21543 check-mu-numberlike-primitive:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21544     # . prologue
21545     55/push-ebp
21546     89/<- %ebp 4/r32/esp
21547     # . save registers
21548     50/push-eax
21549     51/push-ecx
21550     56/push-esi
21551     # esi = stmt
21552     8b/-> *(ebp+8) 6/r32/esi
21553     # var gas/ecx: int = 2
21554     b9/copy-to-ecx 2/imm32
21555     # - check at most 1 output
21556     # var output/eax: (addr stmt-var) = stmt->outputs
21557     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
21558     {
21559       3d/compare-eax-and 0/imm32
21560       74/jump-if-= break/disp8
21561 $check-mu-numberlike-primitive:output:
21562       (check-mu-numberlike-output %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21563       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
21564       3d/compare-eax-and 0/imm32
21565       0f 85/jump-if-!= $check-mu-numberlike-primitive:error-too-many-outputs/disp32
21566       # check output is in a register
21567       # --gas
21568       49/decrement-ecx
21569     }
21570     # - check first inout
21571     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
21572     {
21573       3d/compare-eax-and 0/imm32
21574       0f 84/jump-if-= $check-mu-numberlike-primitive:end/disp32
21575 $check-mu-numberlike-primitive:first-inout:
21576       (check-mu-numberlike-arg %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21577       # --gas
21578       49/decrement-ecx
21579     }
21580     # - check second inout
21581     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
21582     {
21583       3d/compare-eax-and 0/imm32
21584       74/jump-if-= $check-mu-numberlike-primitive:end/disp8
21585 $check-mu-numberlike-primitive:second-inout:
21586       # is a second inout allowed?
21587       81 7/subop/compare %ecx 0/imm32
21588       0f 84/jump-if-= $check-mu-numberlike-primitive:error-too-many-inouts/disp32
21589 $check-mu-numberlike-primitive:second-inout-permitted:
21590       (check-mu-numberlike-arg %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21591     }
21592 $check-mu-numberlike-primitive:third-inout:
21593     # if there's a third arg, raise an error
21594     81 7/subop/compare *(eax+8) 0/imm32  # Stmt-var-next
21595     0f 85/jump-if-!= $check-mu-numberlike-primitive:error-too-many-inouts/disp32
21596 $check-mu-numberlike-primitive:end:
21597     # . restore registers
21598     5e/pop-to-esi
21599     59/pop-to-ecx
21600     58/pop-to-eax
21601     # . epilogue
21602     89/<- %esp 5/r32/ebp
21603     5d/pop-to-ebp
21604     c3/return
21605 
21606 $check-mu-numberlike-primitive:error-too-many-inouts:
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 ")
21612     (lookup *(esi+4) *(esi+8))  # Stmt1-operation Stmt1-operation => eax
21613     (write-buffered *(ebp+0x10) %eax)
21614     (write-buffered *(ebp+0x10) ": too many inouts; most primitives support at most two arguments, across inouts and outputs\n")
21615     (flush *(ebp+0x10))
21616     (stop *(ebp+0x14) 1)
21617     # never gets here
21618 
21619 $check-mu-numberlike-primitive:error-too-many-outputs:
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 ")
21625     (lookup *(esi+4) *(esi+8))  # Stmt1-operation Stmt1-operation => eax
21626     (write-buffered *(ebp+0x10) %eax)
21627     (write-buffered *(ebp+0x10) ": too many outputs; most primitives support at most one output\n")
21628     (flush *(ebp+0x10))
21629     (stop *(ebp+0x14) 1)
21630     # never gets here
21631 
21632 check-mu-numberlike-arg:  # v: (addr stmt-var), stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21633     # . prologue
21634     55/push-ebp
21635     89/<- %ebp 4/r32/esp
21636     # . save registers
21637     50/push-eax
21638     56/push-esi
21639     # var t/esi: (addr type-tree) = lookup(v->value->type)
21640     8b/-> *(ebp+8) 0/r32/eax
21641     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
21642     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
21643     89/<- %esi 0/r32/eax
21644 $check-mu-numberlike-arg:check-literal:
21645     # if t is an int, return
21646     (is-simple-mu-type? %esi 0)  # literal => eax
21647     3d/compare-eax-and 0/imm32/false
21648     0f 85/jump-if-!= $check-mu-numberlike-arg:end/disp32
21649 $check-mu-numberlike-arg:check-addr:
21650     # if t is an addr and v is dereferenced, return whether t->payload is an addr
21651     {
21652       (is-mu-addr-type? %esi)  # => eax
21653       3d/compare-eax-and 0/imm32/false
21654       74/jump-if-= break/disp8
21655       8b/-> *(ebp+8) 0/r32/eax
21656       8b/-> *(eax+0x10) 0/r32/eax  # Stmt-var-is-deref
21657       3d/compare-eax-and 0/imm32/false
21658       {
21659         74/jump-if-= break/disp8
21660         (lookup *(esi+0xc) *(esi+0x10))  # Type-tree-right Type-tree-right => eax
21661         # if t->right is null, t = t->left
21662         81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
21663         {
21664           75/jump-if-!= break/disp8
21665           (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
21666         }
21667         (is-mu-addr-type? %eax)  # => eax
21668         3d/compare-eax-and 0/imm32/false
21669         74/jump-if-= $check-mu-numberlike-arg:end/disp8
21670       }
21671     }
21672 $check-mu-numberlike-arg:output-checks:
21673     (check-mu-numberlike-output *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18))
21674 $check-mu-numberlike-arg:end:
21675     # . restore registers
21676     5e/pop-to-esi
21677     58/pop-to-eax
21678     # . epilogue
21679     89/<- %esp 5/r32/ebp
21680     5d/pop-to-ebp
21681     c3/return
21682 
21683 check-mu-numberlike-output:  # v: (addr stmt-var), stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21684     # . prologue
21685     55/push-ebp
21686     89/<- %ebp 4/r32/esp
21687     # . save registers
21688     50/push-eax
21689     #
21690     (is-mu-numberlike-output-var? *(ebp+8))  # => eax
21691     3d/compare-eax-and 0/imm32/false
21692     0f 84/jump-if-= $check-mu-numberlike-output:fail/disp32
21693 $check-mu-numberlike-output:end:
21694     # . restore registers
21695     58/pop-to-eax
21696     # . epilogue
21697     89/<- %esp 5/r32/ebp
21698     5d/pop-to-ebp
21699     c3/return
21700 
21701 $check-mu-numberlike-output:fail:
21702     # otherwise raise an error
21703     (write-buffered *(ebp+0x14) "fn ")
21704     8b/-> *(ebp+0x10) 0/r32/eax
21705     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21706     (write-buffered *(ebp+0x14) %eax)
21707     (write-buffered *(ebp+0x14) ": stmt ")
21708     8b/-> *(ebp+0xc) 0/r32/eax
21709     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
21710     (write-buffered *(ebp+0x14) %eax)
21711     (write-buffered *(ebp+0x14) ": '")
21712     8b/-> *(ebp+8) 0/r32/eax
21713     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
21714     (lookup *eax *(eax+4))  # Var-name Var-name => eax
21715     (write-buffered *(ebp+0x14) %eax)
21716     (write-buffered *(ebp+0x14) "' must be a non-addr non-offset scalar\n")
21717     (flush *(ebp+0x14))
21718     (stop *(ebp+0x18) 1)
21719     # never gets here
21720 
21721 is-mu-numberlike-output-var?:  # v: (addr stmt-var) -> result/eax: boolean
21722     # . prologue
21723     55/push-ebp
21724     89/<- %ebp 4/r32/esp
21725     #
21726     8b/-> *(ebp+8) 0/r32/eax
21727     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
21728     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
21729     (is-mu-numberlike-output? %eax)  # => eax
21730 $is-mu-numberlike-output-var?:end:
21731     # . epilogue
21732     89/<- %esp 5/r32/ebp
21733     5d/pop-to-ebp
21734     c3/return
21735 
21736 is-mu-numberlike-output?:  # v: (addr type-tree) -> result/eax: boolean
21737     # . prologue
21738     55/push-ebp
21739     89/<- %ebp 4/r32/esp
21740     # . save registers
21741     56/push-esi
21742     # var t/esi: (addr type-tree) = lookup(v->value->type)
21743     8b/-> *(ebp+8) 6/r32/esi
21744 $is-mu-numberlike-output?:check-int:
21745     # if t is an int, return
21746     (is-simple-mu-type? %esi 1)  # int => eax
21747     3d/compare-eax-and 0/imm32/false
21748     0f 85/jump-if-!= $is-mu-numberlike-output?:return-true/disp32
21749 $is-mu-numberlike-output?:check-float:
21750     # if t is a float, return
21751     (is-simple-mu-type? %esi 0xf)  # float => eax
21752     3d/compare-eax-and 0/imm32/false
21753     75/jump-if-!= $is-mu-numberlike-output?:return-true/disp8
21754 $is-mu-numberlike-output?:check-boolean:
21755     # if t is a boolean, return
21756     (is-simple-mu-type? %esi 5)  # boolean => eax
21757     3d/compare-eax-and 0/imm32/false
21758     75/jump-if-!= $is-mu-numberlike-output?:return-true/disp8
21759 $is-mu-numberlike-output?:check-byte:
21760     # if t is a byte, return
21761     (is-simple-mu-type? %esi 8)  # byte => eax
21762     3d/compare-eax-and 0/imm32/false
21763     75/jump-if-!= $is-mu-numberlike-output?:return-true/disp8
21764 $is-mu-numberlike-output?:check-code-point:
21765     # if t is a code-point, return
21766     (is-simple-mu-type? %esi 0xd)  # code-point => eax
21767     3d/compare-eax-and 0/imm32/false
21768     75/jump-if-!= $is-mu-numberlike-output?:return-true/disp8
21769 $is-mu-numberlike-output?:check-grapheme:
21770     # if t is a grapheme, return
21771     (is-simple-mu-type? %esi 0xe)  # grapheme => eax
21772     3d/compare-eax-and 0/imm32/false
21773     75/jump-if-!= $is-mu-numberlike-output?:return-true/disp8
21774 $is-mu-numberlike-output?:return-false:
21775     b8/copy-to-eax 0/imm32/false
21776     eb/jump $is-mu-numberlike-output?:end/disp8
21777 $is-mu-numberlike-output?:return-true:
21778     b8/copy-to-eax 1/imm32/true
21779 $is-mu-numberlike-output?:end:
21780     # . restore registers
21781     5e/pop-to-esi
21782     # . epilogue
21783     89/<- %esp 5/r32/ebp
21784     5d/pop-to-ebp
21785     c3/return
21786 
21787 check-mu-copy-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21788     # . prologue
21789     55/push-ebp
21790     89/<- %ebp 4/r32/esp
21791     # . save registers
21792     50/push-eax
21793     51/push-ecx
21794     52/push-edx
21795     56/push-esi
21796     57/push-edi
21797     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
21798     81 5/subop/subtract %esp 0x60/imm32
21799     68/push 0x60/imm32/size
21800     68/push 0/imm32/read
21801     68/push 0/imm32/write
21802     89/<- %edx 4/r32/esp
21803 $check-mu-copy-stmt:get-output:
21804     # esi = stmt
21805     8b/-> *(ebp+8) 6/r32/esi
21806     # var output/edi: (addr stmt-var) = stmt->outputs
21807     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
21808     89/<- %edi 0/r32/eax
21809     # zero outputs
21810     3d/compare-eax-and 0/imm32
21811     0f 84/jump-if-= $check-mu-copy-stmt:error-no-output/disp32
21812     # > 1 output
21813     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
21814     3d/compare-eax-and 0/imm32
21815     0f 85/jump-if-!= $check-mu-copy-stmt:error-too-many-outputs/disp32
21816 $check-mu-copy-stmt:get-inout:
21817     # var inout/esi: (addr stmt-var) = stmt->inouts
21818     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
21819     89/<- %esi 0/r32/eax
21820     # zero inouts
21821     3d/compare-eax-and 0/imm32
21822     0f 84/jump-if-= $check-mu-copy-stmt:error-no-inout/disp32
21823     # > 1 inout
21824     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
21825     3d/compare-eax-and 0/imm32
21826     0f 85/jump-if-!= $check-mu-copy-stmt:error-too-many-inouts/disp32
21827 $check-mu-copy-stmt:types:
21828     # if inout is not a scalar, abort
21829     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
21830     (size-of %eax)  # => eax
21831     3d/compare-eax-and 4/imm32
21832     0f 8f/jump-if-> $check-mu-copy-stmt:error-inout-too-large/disp32
21833     # var inout-type/ecx: (addr type-tree) = inout->value->type
21834     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
21835     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
21836     89/<- %ecx 0/r32/eax
21837     # if (inout->is-deref?) inout-type = inout-type->payload
21838     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
21839     3d/compare-eax-and 0/imm32/false
21840     {
21841       74/jump-if-= break/disp8
21842       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
21843       # if inout-type->right is null, t = inout-type->left
21844       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
21845       {
21846         75/jump-if-!= break/disp8
21847         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
21848       }
21849       89/<- %ecx 0/r32/eax
21850     }
21851     # if output not in register, abort
21852     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
21853     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
21854     3d/compare-eax-and 0/imm32
21855     0f 84/jump-if-= $check-mu-copy-stmt:error-output-not-in-register/disp32
21856     # var output-type/eax: (addr type-tree) = output->value->type
21857     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
21858     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
21859     # if (inout-type == output-type) return
21860     (type-match? %eax %ecx %edx)  # => eax
21861     3d/compare-eax-and 0/imm32
21862     0f 85/jump-if-!= $check-mu-copy-stmt:end/disp32
21863     # if output is an addr and inout is 0, return
21864     {
21865       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
21866       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
21867       (is-mu-addr-type? %eax)  # => eax
21868       3d/compare-eax-and 0/imm32/false
21869       74/jump-if-= break/disp8
21870       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
21871       (lookup *eax *(eax+4))  # Var-name Var-name => eax
21872       (string-equal? %eax "0")  # => eax
21873       3d/compare-eax-and 0/imm32/false
21874       74/jump-if-= break/disp8
21875       e9/jump $check-mu-copy-stmt:end/disp32
21876     }
21877     # if output is an offset and inout is 0, return
21878     {
21879       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
21880       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
21881       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
21882       75/jump-if-!= break/disp8
21883       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
21884       (is-simple-mu-type? %eax 7)  # offset => eax
21885       3d/compare-eax-and 0/imm32/false
21886       74/jump-if-= break/disp8
21887       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
21888       (lookup *eax *(eax+4))  # Var-name Var-name => eax
21889       (string-equal? %eax "0")  # => eax
21890       3d/compare-eax-and 0/imm32/false
21891       74/jump-if-= break/disp8
21892       e9/jump $check-mu-copy-stmt:end/disp32
21893     }
21894     # if output is a byte, abort if inout is not a literal. Otherwise return.
21895     {
21896       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
21897       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
21898       (is-simple-mu-type? %eax 8)  # byte => eax
21899       3d/compare-eax-and 0/imm32/false
21900       74/jump-if-= break/disp8
21901       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
21902       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
21903       (is-simple-mu-type? %eax 0)  # literal => eax
21904       3d/compare-eax-and 0/imm32/false
21905       0f 84/jump-if-= $check-mu-copy-stmt:error-non-literal-to-byte/disp32
21906       eb/jump $check-mu-copy-stmt:end/disp8
21907     }
21908     # if output is not number-like, abort
21909     (check-mu-numberlike-output %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21910 $check-mu-copy-stmt:end:
21911     # . reclaim locals
21912     81 0/subop/add %esp 0x6c/imm32
21913     # . restore registers
21914     5f/pop-to-edi
21915     5e/pop-to-esi
21916     5a/pop-to-edx
21917     59/pop-to-ecx
21918     58/pop-to-eax
21919     # . epilogue
21920     89/<- %esp 5/r32/ebp
21921     5d/pop-to-ebp
21922     c3/return
21923 
21924 $check-mu-copy-stmt:error-no-inout:
21925     (write-buffered *(ebp+0x10) "fn ")
21926     8b/-> *(ebp+0xc) 0/r32/eax
21927     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21928     (write-buffered *(ebp+0x10) %eax)
21929     (write-buffered *(ebp+0x10) ": stmt 'copy' expects an inout\n")
21930     (flush *(ebp+0x10))
21931     (stop *(ebp+0x14) 1)
21932     # never gets here
21933 
21934 $check-mu-copy-stmt:error-too-many-inouts:
21935     (write-buffered *(ebp+0x10) "fn ")
21936     8b/-> *(ebp+0xc) 0/r32/eax
21937     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21938     (write-buffered *(ebp+0x10) %eax)
21939     (write-buffered *(ebp+0x10) ": stmt 'copy' must have just one inout\n")
21940     (flush *(ebp+0x10))
21941     (stop *(ebp+0x14) 1)
21942     # never gets here
21943 
21944 $check-mu-copy-stmt:error-no-output:
21945     (write-buffered *(ebp+0x10) "fn ")
21946     8b/-> *(ebp+0xc) 0/r32/eax
21947     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21948     (write-buffered *(ebp+0x10) %eax)
21949     (write-buffered *(ebp+0x10) ": stmt 'copy' expects an output\n")
21950     (flush *(ebp+0x10))
21951     (stop *(ebp+0x14) 1)
21952     # never gets here
21953 
21954 $check-mu-copy-stmt:error-output-not-in-register:
21955     (write-buffered *(ebp+0x10) "fn ")
21956     8b/-> *(ebp+0xc) 0/r32/eax
21957     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21958     (write-buffered *(ebp+0x10) %eax)
21959     (write-buffered *(ebp+0x10) ": stmt copy: output '")
21960     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
21961     (lookup *eax *(eax+4))  # Var-name Var-name => eax
21962     (write-buffered *(ebp+0x10) %eax)
21963     (write-buffered *(ebp+0x10) "' not in a register\n")
21964     (flush *(ebp+0x10))
21965     (stop *(ebp+0x14) 1)
21966     # never gets here
21967 
21968 $check-mu-copy-stmt:error-too-many-outputs:
21969     (write-buffered *(ebp+0x10) "fn ")
21970     8b/-> *(ebp+0xc) 0/r32/eax
21971     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21972     (write-buffered *(ebp+0x10) %eax)
21973     (write-buffered *(ebp+0x10) ": stmt 'copy' must have just one output\n")
21974     (flush *(ebp+0x10))
21975     (stop *(ebp+0x14) 1)
21976     # never gets here
21977 
21978 $check-mu-copy-stmt:error-inout-too-large:
21979     (write-buffered *(ebp+0x10) "fn ")
21980     8b/-> *(ebp+0xc) 0/r32/eax
21981     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21982     (write-buffered *(ebp+0x10) %eax)
21983     (write-buffered *(ebp+0x10) ": stmt copy: '")
21984     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
21985     (lookup *eax *(eax+4))  # Var-name Var-name => eax
21986     (write-buffered *(ebp+0x10) %eax)
21987     (write-buffered *(ebp+0x10) "' is too large to fit in a register\n")
21988     (flush *(ebp+0x10))
21989     (stop *(ebp+0x14) 1)
21990     # never gets here
21991 
21992 $check-mu-copy-stmt:error-non-literal-to-byte:
21993     (write-buffered *(ebp+0x10) "fn ")
21994     8b/-> *(ebp+0xc) 0/r32/eax
21995     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21996     (write-buffered *(ebp+0x10) %eax)
21997     (write-buffered *(ebp+0x10) ": stmt copy: cannot copy non-literal to '")
21998     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
21999     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22000     (write-buffered *(ebp+0x10) %eax)
22001     (write-buffered *(ebp+0x10) "' of type byte; use copy-byte\n")
22002     (flush *(ebp+0x10))
22003     (stop *(ebp+0x14) 1)
22004     # never gets here
22005 
22006 check-mu-copy-to-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
22007     # . prologue
22008     55/push-ebp
22009     89/<- %ebp 4/r32/esp
22010     # . save registers
22011     50/push-eax
22012     51/push-ecx
22013     52/push-edx
22014     53/push-ebx
22015     56/push-esi
22016     57/push-edi
22017     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
22018     81 5/subop/subtract %esp 0x60/imm32
22019     68/push 0x60/imm32/size
22020     68/push 0/imm32/read
22021     68/push 0/imm32/write
22022     89/<- %edx 4/r32/esp
22023     # esi = stmt
22024     8b/-> *(ebp+8) 6/r32/esi
22025 $check-mu-copy-to-stmt:check-for-output:
22026     # if stmt->outputs abort
22027     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
22028     3d/compare-eax-and 0/imm32
22029     0f 85/jump-if-!= $check-mu-copy-to-stmt:error-too-many-outputs/disp32
22030 $check-mu-copy-to-stmt:get-dest:
22031     # var dest/edi: (addr stmt-var) = stmt->inouts
22032     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22033     89/<- %edi 0/r32/eax
22034     # zero inouts
22035     3d/compare-eax-and 0/imm32
22036     0f 84/jump-if-= $check-mu-copy-to-stmt:error-incorrect-inouts/disp32
22037 $check-mu-copy-to-stmt:get-src:
22038     # var src/esi: (addr stmt-var) = dest->next
22039     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
22040     89/<- %esi 0/r32/eax
22041     # 1 inout
22042     3d/compare-eax-and 0/imm32
22043     0f 84/jump-if-= $check-mu-copy-to-stmt:error-incorrect-inouts/disp32
22044     # > 2 inouts
22045     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
22046     3d/compare-eax-and 0/imm32
22047     0f 85/jump-if-!= $check-mu-copy-to-stmt:error-incorrect-inouts/disp32
22048 $check-mu-copy-to-stmt:types:
22049     # if src is not a scalar, abort
22050     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22051     (size-of %eax)  # => eax
22052     3d/compare-eax-and 4/imm32
22053     0f 8f/jump-if-> $check-mu-copy-to-stmt:error-src-too-large/disp32
22054     # var src-type/ecx: (addr type-tree) = src->value->type
22055     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22056     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22057     89/<- %ecx 0/r32/eax
22058     # if src not in register or literal, abort
22059     # (we can't use stack-offset because it hasn't been computed yet)
22060     {
22061       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22062       (lookup *(eax+0x8) *(eax+0xc))  # Var-type Var-type => eax
22063       (is-simple-mu-type? %eax 0)  # => eax
22064       3d/compare-eax-and 0/imm32
22065       75/jump-if-!= break/disp8
22066       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22067       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
22068       3d/compare-eax-and 0/imm32
22069       75/jump-if-!= break/disp8
22070       e9/jump $check-mu-copy-to-stmt:error-src-not-literal-or-in-register/disp32
22071     }
22072     # var dest-type/ebx: (addr type-tree) = dest->value->type
22073     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22074     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22075     89/<- %ebx 0/r32/eax
22076     # if (dest->is-deref?) dest-type = dest-type->payload
22077 $check-mu-copy-to-stmt:check-dest-deref:
22078     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
22079     3d/compare-eax-and 0/imm32/false
22080     {
22081       74/jump-if-= break/disp8
22082       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
22083 $check-mu-copy-to-stmt:dest-is-deref:
22084       # if dest-type->right is null, dest-type = dest-type->left
22085       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
22086       {
22087         75/jump-if-!= break/disp8
22088 $check-mu-copy-to-stmt:dest-is-deref2:
22089         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
22090       }
22091       89/<- %ebx 0/r32/eax
22092     }
22093     # if dest is a byte and src is not a literal, abort
22094     {
22095 $check-mu-copy-to-stmt:final-check-byte:
22096       (is-simple-mu-type? %ebx 8)  # byte => eax
22097       3d/compare-eax-and 0/imm32/false
22098       74/jump-if-= break/disp8
22099       (is-simple-mu-type? %ecx 0)  # literal => eax
22100       3d/compare-eax-and 0/imm32/false
22101       0f 84/jump-if-= $check-mu-copy-to-stmt:error-non-literal-to-byte/disp32
22102     }
22103     # if (src-type == dest-type) return
22104     (type-match? %ebx %ecx %edx)  # => eax
22105     3d/compare-eax-and 0/imm32
22106     0f 85/jump-if-!= $check-mu-copy-to-stmt:end/disp32
22107     # if dest is an addr and src is 0, return
22108     {
22109 $check-mu-copy-to-stmt:final-check-addr:
22110       (is-mu-addr-type? %ebx)  # => eax
22111       3d/compare-eax-and 0/imm32/false
22112       74/jump-if-= break/disp8
22113       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22114       (lookup *eax *(eax+4))  # Var-name Var-name => eax
22115       (string-equal? %eax "0")  # => eax
22116       3d/compare-eax-and 0/imm32/false
22117       74/jump-if-= break/disp8
22118       e9/jump $check-mu-copy-to-stmt:end/disp32
22119     }
22120     # if dest is an offset and src is 0, return
22121     {
22122 $check-mu-copy-to-stmt:final-check-offset:
22123       81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
22124       75/jump-if-!= break/disp8
22125       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
22126       (is-simple-mu-type? %eax 7)  # offset => eax
22127       3d/compare-eax-and 0/imm32/false
22128       74/jump-if-= break/disp8
22129       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22130       (lookup *eax *(eax+4))  # Var-name Var-name => eax
22131       (string-equal? %eax "0")  # => eax
22132       3d/compare-eax-and 0/imm32/false
22133       74/jump-if-= break/disp8
22134       e9/jump $check-mu-copy-to-stmt:end/disp32
22135     }
22136     # if dest is not number-like, abort
22137     (check-mu-numberlike-arg %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
22138 $check-mu-copy-to-stmt:end:
22139     # . reclaim locals
22140     81 0/subop/add %esp 0x6c/imm32
22141     # . restore registers
22142     5f/pop-to-edi
22143     5e/pop-to-esi
22144     5b/pop-to-ebx
22145     5a/pop-to-edx
22146     59/pop-to-ecx
22147     58/pop-to-eax
22148     # . epilogue
22149     89/<- %esp 5/r32/ebp
22150     5d/pop-to-ebp
22151     c3/return
22152 
22153 $check-mu-copy-to-stmt:error-incorrect-inouts:
22154     (write-buffered *(ebp+0x10) "fn ")
22155     8b/-> *(ebp+0xc) 0/r32/eax
22156     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22157     (write-buffered *(ebp+0x10) %eax)
22158     (write-buffered *(ebp+0x10) ": stmt 'copy-to' must have two inouts\n")
22159     (flush *(ebp+0x10))
22160     (stop *(ebp+0x14) 1)
22161     # never gets here
22162 
22163 $check-mu-copy-to-stmt:error-too-many-outputs:
22164     (write-buffered *(ebp+0x10) "fn ")
22165     8b/-> *(ebp+0xc) 0/r32/eax
22166     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22167     (write-buffered *(ebp+0x10) %eax)
22168     (write-buffered *(ebp+0x10) ": stmt 'copy-to' must not have any outputs\n")
22169     (flush *(ebp+0x10))
22170     (stop *(ebp+0x14) 1)
22171     # never gets here
22172 
22173 $check-mu-copy-to-stmt:error-src-not-literal-or-in-register:
22174     (write-buffered *(ebp+0x10) "fn ")
22175     8b/-> *(ebp+0xc) 0/r32/eax
22176     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22177     (write-buffered *(ebp+0x10) %eax)
22178     (write-buffered *(ebp+0x10) ": stmt copy-to: source (second inout) is in memory\n")
22179     (flush *(ebp+0x10))
22180     (stop *(ebp+0x14) 1)
22181     # never gets here
22182 
22183 $check-mu-copy-to-stmt:error-src-too-large:
22184     (write-buffered *(ebp+0x10) "fn ")
22185     8b/-> *(ebp+0xc) 0/r32/eax
22186     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22187     (write-buffered *(ebp+0x10) %eax)
22188     (write-buffered *(ebp+0x10) ": stmt copy-to: '")
22189     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22190     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22191     (write-buffered *(ebp+0x10) %eax)
22192     (write-buffered *(ebp+0x10) "' is too large to copy\n")
22193     (flush *(ebp+0x10))
22194     (stop *(ebp+0x14) 1)
22195     # never gets here
22196 
22197 $check-mu-copy-to-stmt:error-non-literal-to-byte:
22198     (write-buffered *(ebp+0x10) "fn ")
22199     8b/-> *(ebp+0xc) 0/r32/eax
22200     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22201     (write-buffered *(ebp+0x10) %eax)
22202     (write-buffered *(ebp+0x10) ": stmt copy-to: cannot copy non-literal to type byte; use copy-byte-to\n")
22203     (flush *(ebp+0x10))
22204     (stop *(ebp+0x14) 1)
22205     # never gets here
22206 
22207 check-mu-copy-byte-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
22208     # . prologue
22209     55/push-ebp
22210     89/<- %ebp 4/r32/esp
22211     # . save registers
22212     50/push-eax
22213     51/push-ecx
22214     52/push-edx
22215     56/push-esi
22216     57/push-edi
22217     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
22218     81 5/subop/subtract %esp 0x60/imm32
22219     68/push 0x60/imm32/size
22220     68/push 0/imm32/read
22221     68/push 0/imm32/write
22222     89/<- %edx 4/r32/esp
22223 $check-mu-copy-byte-stmt:get-output:
22224     # esi = stmt
22225     8b/-> *(ebp+8) 6/r32/esi
22226     # var output/edi: (addr stmt-var) = stmt->outputs
22227     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
22228     89/<- %edi 0/r32/eax
22229     # zero outputs
22230     3d/compare-eax-and 0/imm32
22231     0f 84/jump-if-= $check-mu-copy-byte-stmt:error-no-output/disp32
22232     # > 1 output
22233     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
22234     3d/compare-eax-and 0/imm32
22235     0f 85/jump-if-!= $check-mu-copy-byte-stmt:error-too-many-outputs/disp32
22236 $check-mu-copy-byte-stmt:get-inout:
22237     # var inout/esi: (addr stmt-var) = stmt->inouts
22238     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22239     89/<- %esi 0/r32/eax
22240     # zero inouts
22241     3d/compare-eax-and 0/imm32
22242     0f 84/jump-if-= $check-mu-copy-byte-stmt:error-no-inout/disp32
22243     # > 1 inout
22244     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
22245     3d/compare-eax-and 0/imm32
22246     0f 85/jump-if-!= $check-mu-copy-byte-stmt:error-too-many-inouts/disp32
22247 $check-mu-copy-byte-stmt:types:
22248     # if inout is not a scalar, abort
22249     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22250     (size-of %eax)  # => eax
22251     3d/compare-eax-and 4/imm32
22252     0f 8f/jump-if-> $check-mu-copy-byte-stmt:error-inout-too-large/disp32
22253     # var inout-type/ecx: (addr type-tree) = inout->value->type
22254     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22255     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22256     89/<- %ecx 0/r32/eax
22257 $check-mu-copy-byte-stmt:check-inout-deref:
22258     # if (inout->is-deref?) inout-type = inout-type->payload
22259     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
22260     3d/compare-eax-and 0/imm32/false
22261     {
22262       74/jump-if-= break/disp8
22263 $check-mu-copy-byte-stmt:inout-is-deref:
22264       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
22265       # if inout-type->right is null, t = inout-type->left
22266       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
22267       {
22268         75/jump-if-!= break/disp8
22269 $check-mu-copy-byte-stmt:inout-is-deref2:
22270         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
22271       }
22272       89/<- %ecx 0/r32/eax
22273     }
22274     # if output not in register, abort
22275     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22276     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
22277     3d/compare-eax-and 0/imm32
22278     0f 84/jump-if-= $check-mu-copy-byte-stmt:error-output-not-in-register/disp32
22279     # var output-type/eax: (addr type-tree) = output->value->type
22280     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22281     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22282     # if output is not of type byte, abort
22283     (is-simple-mu-type? %eax 8)  # byte => eax
22284     3d/compare-eax-and 0/imm32
22285     0f 84/jump-if-= $check-mu-copy-byte-stmt:error-invalid-output-type/disp32
22286 $check-mu-copy-byte-stmt:end:
22287     # . reclaim locals
22288     81 0/subop/add %esp 0x6c/imm32
22289     # . restore registers
22290     5f/pop-to-edi
22291     5e/pop-to-esi
22292     5a/pop-to-edx
22293     59/pop-to-ecx
22294     58/pop-to-eax
22295     # . epilogue
22296     89/<- %esp 5/r32/ebp
22297     5d/pop-to-ebp
22298     c3/return
22299 
22300 $check-mu-copy-byte-stmt:error-no-inout:
22301     (write-buffered *(ebp+0x10) "fn ")
22302     8b/-> *(ebp+0xc) 0/r32/eax
22303     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22304     (write-buffered *(ebp+0x10) %eax)
22305     (write-buffered *(ebp+0x10) ": stmt 'copy-byte' expects an inout\n")
22306     (flush *(ebp+0x10))
22307     (stop *(ebp+0x14) 1)
22308     # never gets here
22309 
22310 $check-mu-copy-byte-stmt:error-too-many-inouts:
22311     (write-buffered *(ebp+0x10) "fn ")
22312     8b/-> *(ebp+0xc) 0/r32/eax
22313     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22314     (write-buffered *(ebp+0x10) %eax)
22315     (write-buffered *(ebp+0x10) ": stmt 'copy-byte' must have just one inout\n")
22316     (flush *(ebp+0x10))
22317     (stop *(ebp+0x14) 1)
22318     # never gets here
22319 
22320 $check-mu-copy-byte-stmt:error-no-output:
22321     (write-buffered *(ebp+0x10) "fn ")
22322     8b/-> *(ebp+0xc) 0/r32/eax
22323     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22324     (write-buffered *(ebp+0x10) %eax)
22325     (write-buffered *(ebp+0x10) ": stmt 'copy-byte' expects an output\n")
22326     (flush *(ebp+0x10))
22327     (stop *(ebp+0x14) 1)
22328     # never gets here
22329 
22330 $check-mu-copy-byte-stmt:error-output-not-in-register:
22331     (write-buffered *(ebp+0x10) "fn ")
22332     8b/-> *(ebp+0xc) 0/r32/eax
22333     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22334     (write-buffered *(ebp+0x10) %eax)
22335     (write-buffered *(ebp+0x10) ": stmt copy-byte: output '")
22336     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22337     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22338     (write-buffered *(ebp+0x10) %eax)
22339     (write-buffered *(ebp+0x10) "' not in a register\n")
22340     (flush *(ebp+0x10))
22341     (stop *(ebp+0x14) 1)
22342     # never gets here
22343 
22344 $check-mu-copy-byte-stmt:error-too-many-outputs:
22345     (write-buffered *(ebp+0x10) "fn ")
22346     8b/-> *(ebp+0xc) 0/r32/eax
22347     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22348     (write-buffered *(ebp+0x10) %eax)
22349     (write-buffered *(ebp+0x10) ": stmt 'copy-byte' must have just one output\n")
22350     (flush *(ebp+0x10))
22351     (stop *(ebp+0x14) 1)
22352     # never gets here
22353 
22354 $check-mu-copy-byte-stmt:error-invalid-output-type:
22355     (write-buffered *(ebp+0x10) "fn ")
22356     8b/-> *(ebp+0xc) 0/r32/eax
22357     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22358     (write-buffered *(ebp+0x10) %eax)
22359     (write-buffered *(ebp+0x10) ": stmt 'copy-byte' must write to output of type byte\n")
22360     (flush *(ebp+0x10))
22361     (stop *(ebp+0x14) 1)
22362     # never gets here
22363 
22364 $check-mu-copy-byte-stmt:error-inout-too-large:
22365     (write-buffered *(ebp+0x10) "fn ")
22366     8b/-> *(ebp+0xc) 0/r32/eax
22367     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22368     (write-buffered *(ebp+0x10) %eax)
22369     (write-buffered *(ebp+0x10) ": stmt copy-byte: '")
22370     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22371     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22372     (write-buffered *(ebp+0x10) %eax)
22373     (write-buffered *(ebp+0x10) "' is too large to fit in a register\n")
22374     (flush *(ebp+0x10))
22375     (stop *(ebp+0x14) 1)
22376     # never gets here
22377 
22378 check-mu-copy-byte-to-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
22379     # . prologue
22380     55/push-ebp
22381     89/<- %ebp 4/r32/esp
22382     # . save registers
22383     50/push-eax
22384     52/push-edx
22385     53/push-ebx
22386     56/push-esi
22387     57/push-edi
22388     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
22389     81 5/subop/subtract %esp 0x60/imm32
22390     68/push 0x60/imm32/size
22391     68/push 0/imm32/read
22392     68/push 0/imm32/write
22393     89/<- %edx 4/r32/esp
22394     # esi = stmt
22395     8b/-> *(ebp+8) 6/r32/esi
22396 $check-mu-copy-byte-to-stmt:check-for-output:
22397     # if stmt->outputs abort
22398     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
22399     3d/compare-eax-and 0/imm32
22400     0f 85/jump-if-!= $check-mu-copy-byte-to-stmt:error-too-many-outputs/disp32
22401 $check-mu-copy-byte-to-stmt:get-dest:
22402     # var dest/edi: (addr stmt-var) = stmt->inouts
22403     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22404     89/<- %edi 0/r32/eax
22405     # zero inouts
22406     3d/compare-eax-and 0/imm32
22407     0f 84/jump-if-= $check-mu-copy-byte-to-stmt:error-incorrect-inouts/disp32
22408 $check-mu-copy-byte-to-stmt:get-src:
22409     # var src/esi: (addr stmt-var) = dest->next
22410     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
22411     89/<- %esi 0/r32/eax
22412     # 1 inout
22413     3d/compare-eax-and 0/imm32
22414     0f 84/jump-if-= $check-mu-copy-byte-to-stmt:error-incorrect-inouts/disp32
22415     # > 2 inouts
22416     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
22417     3d/compare-eax-and 0/imm32
22418     0f 85/jump-if-!= $check-mu-copy-byte-to-stmt:error-incorrect-inouts/disp32
22419 $check-mu-copy-byte-to-stmt:types:
22420     # if src is not a scalar, abort
22421     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22422     (size-of %eax)  # => eax
22423     3d/compare-eax-and 4/imm32
22424     0f 8f/jump-if-> $check-mu-copy-byte-to-stmt:error-src-too-large/disp32
22425     # if src not in register, abort
22426     {
22427       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22428       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
22429       3d/compare-eax-and 0/imm32
22430       75/jump-if-!= break/disp8
22431       e9/jump $check-mu-copy-byte-to-stmt:error-src-not-in-register/disp32
22432     }
22433     # var dest-type/ebx: (addr type-tree) = dest->value->type
22434     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22435     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22436     89/<- %ebx 0/r32/eax
22437     # if (dest->is-deref?) dest-type = dest-type->payload
22438 $check-mu-copy-byte-to-stmt:check-dest-deref:
22439     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
22440     3d/compare-eax-and 0/imm32/false
22441     {
22442       74/jump-if-= break/disp8
22443       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
22444 $check-mu-copy-byte-to-stmt:dest-is-deref:
22445       # if dest-type->right is null, dest-type = dest-type->left
22446       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
22447       {
22448         75/jump-if-!= break/disp8
22449 $check-mu-copy-byte-to-stmt:dest-is-deref2:
22450         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
22451       }
22452       89/<- %ebx 0/r32/eax
22453     }
22454     # if dest is not a byte, abort
22455     (is-simple-mu-type? %ebx 8)  # byte => eax
22456     3d/compare-eax-and 0/imm32/false
22457     0f 84/jump-if-= $check-mu-copy-byte-to-stmt:error-invalid-dest-type/disp32
22458 $check-mu-copy-byte-to-stmt:end:
22459     # . reclaim locals
22460     81 0/subop/add %esp 0x6c/imm32
22461     # . restore registers
22462     5f/pop-to-edi
22463     5e/pop-to-esi
22464     5b/pop-to-ebx
22465     5a/pop-to-edx
22466     58/pop-to-eax
22467     # . epilogue
22468     89/<- %esp 5/r32/ebp
22469     5d/pop-to-ebp
22470     c3/return
22471 
22472 $check-mu-copy-byte-to-stmt:error-incorrect-inouts:
22473     (write-buffered *(ebp+0x10) "fn ")
22474     8b/-> *(ebp+0xc) 0/r32/eax
22475     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22476     (write-buffered *(ebp+0x10) %eax)
22477     (write-buffered *(ebp+0x10) ": stmt 'copy-byte-to' must have two inouts\n")
22478     (flush *(ebp+0x10))
22479     (stop *(ebp+0x14) 1)
22480     # never gets here
22481 
22482 $check-mu-copy-byte-to-stmt:error-too-many-outputs:
22483     (write-buffered *(ebp+0x10) "fn ")
22484     8b/-> *(ebp+0xc) 0/r32/eax
22485     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22486     (write-buffered *(ebp+0x10) %eax)
22487     (write-buffered *(ebp+0x10) ": stmt 'copy-byte-to' must not have any outputs\n")
22488     (flush *(ebp+0x10))
22489     (stop *(ebp+0x14) 1)
22490     # never gets here
22491 
22492 $check-mu-copy-byte-to-stmt:error-src-not-in-register:
22493     (write-buffered *(ebp+0x10) "fn ")
22494     8b/-> *(ebp+0xc) 0/r32/eax
22495     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22496     (write-buffered *(ebp+0x10) %eax)
22497     (write-buffered *(ebp+0x10) ": stmt copy-byte-to: source (second inout) must be in a register\n")
22498     (flush *(ebp+0x10))
22499     (stop *(ebp+0x14) 1)
22500     # never gets here
22501 
22502 $check-mu-copy-byte-to-stmt:error-invalid-dest-type:
22503     (write-buffered *(ebp+0x10) "fn ")
22504     8b/-> *(ebp+0xc) 0/r32/eax
22505     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22506     (write-buffered *(ebp+0x10) %eax)
22507     (write-buffered *(ebp+0x10) ": stmt copy-byte-to: '")
22508     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22509     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22510     (write-buffered *(ebp+0x10) %eax)
22511     (write-buffered *(ebp+0x10) "' must be a byte\n")
22512     (flush *(ebp+0x10))
22513     (stop *(ebp+0x14) 1)
22514     # never gets here
22515 
22516 $check-mu-copy-byte-to-stmt:error-src-too-large:
22517     (write-buffered *(ebp+0x10) "fn ")
22518     8b/-> *(ebp+0xc) 0/r32/eax
22519     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22520     (write-buffered *(ebp+0x10) %eax)
22521     (write-buffered *(ebp+0x10) ": stmt copy-byte-to: '")
22522     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22523     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22524     (write-buffered *(ebp+0x10) %eax)
22525     (write-buffered *(ebp+0x10) "' is too large to copy\n")
22526     (flush *(ebp+0x10))
22527     (stop *(ebp+0x14) 1)
22528     # never gets here
22529 
22530 check-mu-compare-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
22531     # . prologue
22532     55/push-ebp
22533     89/<- %ebp 4/r32/esp
22534     # . save registers
22535     50/push-eax
22536     51/push-ecx
22537     52/push-edx
22538     53/push-ebx
22539     56/push-esi
22540     57/push-edi
22541     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
22542     81 5/subop/subtract %esp 0x60/imm32
22543     68/push 0x60/imm32/size
22544     68/push 0/imm32/read
22545     68/push 0/imm32/write
22546     89/<- %edx 4/r32/esp
22547     # esi = stmt
22548     8b/-> *(ebp+8) 6/r32/esi
22549 $check-mu-compare-stmt:check-for-output:
22550     # if stmt->outputs abort
22551     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
22552     3d/compare-eax-and 0/imm32
22553     0f 85/jump-if-!= $check-mu-compare-stmt:error-too-many-outputs/disp32
22554 $check-mu-compare-stmt:get-left:
22555     # var left/edi: (addr stmt-var) = stmt->inouts
22556     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22557     89/<- %edi 0/r32/eax
22558     # zero inouts
22559     3d/compare-eax-and 0/imm32
22560     0f 84/jump-if-= $check-mu-compare-stmt:error-incorrect-inouts/disp32
22561 $check-mu-compare-stmt:get-right:
22562     # var right/esi: (addr stmt-var) = left->next
22563     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
22564     89/<- %esi 0/r32/eax
22565     # 1 inout
22566     3d/compare-eax-and 0/imm32
22567     0f 84/jump-if-= $check-mu-compare-stmt:error-incorrect-inouts/disp32
22568     # > 2 inouts
22569     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
22570     3d/compare-eax-and 0/imm32
22571     0f 85/jump-if-!= $check-mu-compare-stmt:error-incorrect-inouts/disp32
22572     # if both inouts are in memory, abort
22573     {
22574 $check-mu-compare-stmt:both-in-mem:
22575       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22576       (lookup *(eax+0x8) *(eax+0xc))  # Var-type Var-type => eax
22577       (is-simple-mu-type? %eax 0)  # => eax
22578       3d/compare-eax-and 0/imm32
22579       0f 85/jump-if-!= break/disp32
22580       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22581       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
22582       3d/compare-eax-and 0/imm32
22583       75/jump-if-!= break/disp8
22584       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22585       (lookup *(eax+0x8) *(eax+0xc))  # Var-type Var-type => eax
22586       (is-simple-mu-type? %eax 0)  # => eax
22587       3d/compare-eax-and 0/imm32
22588       75/jump-if-!= break/disp8
22589       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22590       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
22591       3d/compare-eax-and 0/imm32
22592       75/jump-if-!= break/disp8
22593       e9/jump $check-mu-compare-stmt:error-both-in-memory/disp32
22594     }
22595 $check-mu-compare-stmt:types:
22596     # var right-type/ecx: (addr type-tree) = right->value->type
22597     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22598     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22599     89/<- %ecx 0/r32/eax
22600     # if (right->is-deref?) right-type = right-type->payload
22601     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
22602     3d/compare-eax-and 0/imm32/false
22603     {
22604       74/jump-if-= break/disp8
22605       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
22606       # if right-type->right is null, right-type = right-type->left
22607       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
22608       {
22609         75/jump-if-!= break/disp8
22610         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
22611       }
22612       89/<- %ecx 0/r32/eax
22613     }
22614     # if right is not a scalar, abort
22615     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22616     (size-of %eax)  # => eax
22617     3d/compare-eax-and 4/imm32
22618     0f 8f/jump-if-> $check-mu-compare-stmt:error-right-too-large/disp32
22619     # if left is not a scalar, abort
22620     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22621     (size-of %eax)  # => eax
22622     3d/compare-eax-and 4/imm32
22623     0f 8f/jump-if-> $check-mu-compare-stmt:error-left-too-large/disp32
22624     # var left-type/ebx: (addr type-tree) = left->value->type
22625     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22626     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22627     89/<- %ebx 0/r32/eax
22628     # if (left->is-deref?) left-type = left-type->payload
22629     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
22630     3d/compare-eax-and 0/imm32/false
22631     {
22632       74/jump-if-= break/disp8
22633       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
22634       # if left-type->right is null, left-type = left-type->left
22635       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
22636       {
22637         75/jump-if-!= break/disp8
22638         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
22639       }
22640       89/<- %ebx 0/r32/eax
22641     }
22642     # if (left-type == right-type) return
22643     (type-match? %ebx %ecx %edx)  # => eax
22644     3d/compare-eax-and 0/imm32
22645     0f 85/jump-if-!= $check-mu-compare-stmt:end/disp32
22646     # if left is an addr and right is 0, return
22647     {
22648       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22649       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22650       (is-mu-addr-type? %eax)  # => eax
22651       3d/compare-eax-and 0/imm32/false
22652       74/jump-if-= break/disp8
22653       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22654       (lookup *eax *(eax+4))  # Var-name Var-name => eax
22655       (string-equal? %eax "0")  # => eax
22656       3d/compare-eax-and 0/imm32/false
22657       74/jump-if-= break/disp8
22658       eb/jump $check-mu-compare-stmt:end/disp8
22659     }
22660     # if left is not number-like, abort
22661     (check-mu-numberlike-arg %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
22662 $check-mu-compare-stmt:end:
22663     # . reclaim locals
22664     81 0/subop/add %esp 0x6c/imm32
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-compare-stmt:error-incorrect-inouts:
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 'compare' must have two inouts\n")
22683     (flush *(ebp+0x10))
22684     (stop *(ebp+0x14) 1)
22685     # never gets here
22686 
22687 $check-mu-compare-stmt:error-too-many-outputs:
22688     (write-buffered *(ebp+0x10) "fn ")
22689     8b/-> *(ebp+0xc) 0/r32/eax
22690     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22691     (write-buffered *(ebp+0x10) %eax)
22692     (write-buffered *(ebp+0x10) ": stmt 'compare' must not have any outputs\n")
22693     (flush *(ebp+0x10))
22694     (stop *(ebp+0x14) 1)
22695     # never gets here
22696 
22697 $check-mu-compare-stmt:error-both-in-memory:
22698     (write-buffered *(ebp+0x10) "fn ")
22699     8b/-> *(ebp+0xc) 0/r32/eax
22700     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22701     (write-buffered *(ebp+0x10) %eax)
22702     (write-buffered *(ebp+0x10) ": stmt compare: both inouts are in memory\n")
22703     (flush *(ebp+0x10))
22704     (stop *(ebp+0x14) 1)
22705     # never gets here
22706 
22707 $check-mu-compare-stmt:error-left-too-large:
22708     (write-buffered *(ebp+0x10) "fn ")
22709     8b/-> *(ebp+0xc) 0/r32/eax
22710     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22711     (write-buffered *(ebp+0x10) %eax)
22712     (write-buffered *(ebp+0x10) ": stmt compare: '")
22713     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22714     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22715     (write-buffered *(ebp+0x10) %eax)
22716     (write-buffered *(ebp+0x10) "' is too large to compare\n")
22717     (flush *(ebp+0x10))
22718     (stop *(ebp+0x14) 1)
22719     # never gets here
22720 
22721 $check-mu-compare-stmt:error-right-too-large:
22722     (write-buffered *(ebp+0x10) "fn ")
22723     8b/-> *(ebp+0xc) 0/r32/eax
22724     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22725     (write-buffered *(ebp+0x10) %eax)
22726     (write-buffered *(ebp+0x10) ": stmt compare: '")
22727     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22728     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22729     (write-buffered *(ebp+0x10) %eax)
22730     (write-buffered *(ebp+0x10) "' is too large to compare\n")
22731     (flush *(ebp+0x10))
22732     (stop *(ebp+0x14) 1)
22733     # never gets here
22734 
22735 check-mu-address-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
22736     # . prologue
22737     55/push-ebp
22738     89/<- %ebp 4/r32/esp
22739     # . save registers
22740     50/push-eax
22741     51/push-ecx
22742     52/push-edx
22743     56/push-esi
22744     57/push-edi
22745 $check-mu-address-stmt:get-output:
22746     # esi = stmt
22747     8b/-> *(ebp+8) 6/r32/esi
22748     # var output/edi: (addr stmt-var) = stmt->outputs
22749     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
22750     89/<- %edi 0/r32/eax
22751     # zero outputs
22752     3d/compare-eax-and 0/imm32
22753     0f 84/jump-if-= $check-mu-address-stmt:error-no-output/disp32
22754     # > 1 output
22755     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
22756     3d/compare-eax-and 0/imm32
22757     0f 85/jump-if-!= $check-mu-address-stmt:error-too-many-outputs/disp32
22758 $check-mu-address-stmt:get-inout:
22759     # var inout/esi: (addr stmt-var) = stmt->inouts
22760     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22761     89/<- %esi 0/r32/eax
22762     # zero inouts
22763     3d/compare-eax-and 0/imm32
22764     0f 84/jump-if-= $check-mu-address-stmt:error-no-inout/disp32
22765     # > 1 inout
22766     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
22767     3d/compare-eax-and 0/imm32
22768     0f 85/jump-if-!= $check-mu-address-stmt:error-too-many-inouts/disp32
22769 $check-mu-address-stmt:types:
22770     # if output not in register, abort
22771     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22772     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
22773     3d/compare-eax-and 0/imm32
22774     0f 84/jump-if-= $check-mu-address-stmt:error-output-not-in-register/disp32
22775     # var output-type/edx: (addr type-tree) = output->value->type
22776     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22777     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22778     89/<- %edx 0/r32/eax
22779     # if output-type not an addr, abort
22780     (is-mu-addr-type? %edx)  # => eax
22781     3d/compare-eax-and 0/imm32/false
22782     0f 84/jump-if-= $check-mu-address-stmt:error-output-not-address/disp32
22783     # output-type = output-type->right
22784     (lookup *(edx+0xc) *(edx+0x10))  # Type-tree-right Type-tree-right => eax
22785     # if output-type->right is null, output-type = output-type->left
22786     81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
22787     {
22788       75/jump-if-!= break/disp8
22789       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
22790     }
22791     89/<- %edx 0/r32/eax
22792     # var inout-type/ecx: (addr type-tree) = inout->value->type
22793     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22794     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22795     89/<- %ecx 0/r32/eax
22796     # if (inout->is-deref?) inout-type = inout-type->payload
22797     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
22798     3d/compare-eax-and 0/imm32/false
22799     {
22800       74/jump-if-= break/disp8
22801       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
22802       # if inout-type->right is null, t = inout-type->left
22803       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
22804       {
22805         75/jump-if-!= break/disp8
22806         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
22807       }
22808       89/<- %ecx 0/r32/eax
22809     }
22810     # if (inout-type != output-type) abort
22811     (type-equal-ignoring-capacity? %edx %ecx)  # => eax
22812     3d/compare-eax-and 0/imm32
22813     0f 84/jump-if-= $check-mu-address-stmt:error-type-mismatch/disp32
22814 $check-mu-address-stmt:end:
22815     # . restore registers
22816     5f/pop-to-edi
22817     5e/pop-to-esi
22818     5a/pop-to-edx
22819     59/pop-to-ecx
22820     58/pop-to-eax
22821     # . epilogue
22822     89/<- %esp 5/r32/ebp
22823     5d/pop-to-ebp
22824     c3/return
22825 
22826 $check-mu-address-stmt:error-no-inout:
22827     (write-buffered *(ebp+0x10) "fn ")
22828     8b/-> *(ebp+0xc) 0/r32/eax
22829     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22830     (write-buffered *(ebp+0x10) %eax)
22831     (write-buffered *(ebp+0x10) ": stmt 'address' expects an inout\n")
22832     (flush *(ebp+0x10))
22833     (stop *(ebp+0x14) 1)
22834     # never gets here
22835 
22836 $check-mu-address-stmt:error-too-many-inouts:
22837     (write-buffered *(ebp+0x10) "fn ")
22838     8b/-> *(ebp+0xc) 0/r32/eax
22839     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22840     (write-buffered *(ebp+0x10) %eax)
22841     (write-buffered *(ebp+0x10) ": stmt 'address' must have just one inout\n")
22842     (flush *(ebp+0x10))
22843     (stop *(ebp+0x14) 1)
22844     # never gets here
22845 
22846 $check-mu-address-stmt:error-no-output:
22847     (write-buffered *(ebp+0x10) "fn ")
22848     8b/-> *(ebp+0xc) 0/r32/eax
22849     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22850     (write-buffered *(ebp+0x10) %eax)
22851     (write-buffered *(ebp+0x10) ": stmt 'address' expects an output\n")
22852     (flush *(ebp+0x10))
22853     (stop *(ebp+0x14) 1)
22854     # never gets here
22855 
22856 $check-mu-address-stmt:error-output-not-in-register:
22857     (write-buffered *(ebp+0x10) "fn ")
22858     8b/-> *(ebp+0xc) 0/r32/eax
22859     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22860     (write-buffered *(ebp+0x10) %eax)
22861     (write-buffered *(ebp+0x10) ": stmt address: output '")
22862     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22863     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22864     (write-buffered *(ebp+0x10) %eax)
22865     (write-buffered *(ebp+0x10) "' not in a register\n")
22866     (flush *(ebp+0x10))
22867     (stop *(ebp+0x14) 1)
22868     # never gets here
22869 
22870 $check-mu-address-stmt:error-too-many-outputs:
22871     (write-buffered *(ebp+0x10) "fn ")
22872     8b/-> *(ebp+0xc) 0/r32/eax
22873     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22874     (write-buffered *(ebp+0x10) %eax)
22875     (write-buffered *(ebp+0x10) ": stmt 'address' must have just one output\n")
22876     (flush *(ebp+0x10))
22877     (stop *(ebp+0x14) 1)
22878     # never gets here
22879 
22880 $check-mu-address-stmt:error-output-not-address:
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 address: output '")
22886     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22887     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22888     (write-buffered *(ebp+0x10) %eax)
22889     (write-buffered *(ebp+0x10) "' is not an addr\n")
22890     (flush *(ebp+0x10))
22891     (stop *(ebp+0x14) 1)
22892     # never gets here
22893 
22894 $check-mu-address-stmt:error-type-mismatch:
22895     (write-buffered *(ebp+0x10) "fn ")
22896     8b/-> *(ebp+0xc) 0/r32/eax
22897     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22898     (write-buffered *(ebp+0x10) %eax)
22899     (write-buffered *(ebp+0x10) ": stmt address: output '")
22900     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22901     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22902     (write-buffered *(ebp+0x10) %eax)
22903     (write-buffered *(ebp+0x10) "' cannot hold address of '")
22904     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22905     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22906     (write-buffered *(ebp+0x10) %eax)
22907     (write-buffered *(ebp+0x10) "'\n")
22908     (flush *(ebp+0x10))
22909     (stop *(ebp+0x14) 1)
22910     # never gets here
22911 
22912 type-equal-ignoring-capacity?:  # a: (addr type-tree), b: (addr type-tree) -> result/eax: boolean
22913     # . prologue
22914     55/push-ebp
22915     89/<- %ebp 4/r32/esp
22916     # . save registers
22917     51/push-ecx
22918     52/push-edx
22919     53/push-ebx
22920     # var curr-a/ecx: (addr type-tree) = a
22921     8b/-> *(ebp+8) 1/r32/ecx
22922     # var curr-b/ebx: (addr type-tree) = b
22923     8b/-> *(ebp+0xc) 3/r32/ebx
22924     # if (curr-a->is-atom?) fall back to regular equality
22925     81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
22926     0f 85/jump-if-!= $type-equal-ignoring-capacity?:base-case/disp32
22927     # if (curr-a->left != curr-b->left) return false
22928     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
22929     89/<- %edx 0/r32/eax
22930     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
22931     (type-equal? %edx %eax)  # => eax
22932     3d/compare-eax-and 0/imm32/false
22933     0f 84/jump-if-= $type-equal-ignoring-capacity?:end/disp32  # eax switches meaning
22934     # if (curr-a->left == "array") curr-a = curr-a->element-type
22935     {
22936       (is-mu-array? %edx)  # => eax
22937       3d/compare-eax-and 0/imm32/false
22938       75/jump-if-!= break/disp8
22939 $type-equal-ignoring-capacity?:array:
22940       # curr-a = curr-a->right->left
22941       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
22942       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
22943       89/<- %ecx 0/r32/eax
22944       # curr-b = curr-b->right->left
22945       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
22946       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
22947       89/<- %ebx 0/r32/eax
22948       eb/jump $type-equal-ignoring-capacity?:base-case/disp8
22949     }
22950     # if (curr-a->left == "stream") curr-a = curr-a->element-type
22951     {
22952       (is-mu-stream? %edx)  # => eax
22953       3d/compare-eax-and 0/imm32/false
22954       75/jump-if-!= break/disp8
22955 $type-equal-ignoring-capacity?:stream:
22956       # curr-a = curr-a->right->left
22957       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
22958       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
22959       89/<- %ecx 0/r32/eax
22960       # curr-b = curr-b->right->left
22961       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
22962       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
22963       89/<- %ebx 0/r32/eax
22964       eb/jump $type-equal-ignoring-capacity?:base-case/disp8
22965     }
22966 $type-equal-ignoring-capacity?:base-case:
22967     # return type-equal?(curr-a, curr-b)
22968     (type-equal? %ecx %ebx)  # => eax
22969 $type-equal-ignoring-capacity?:end:
22970     # . restore registers
22971     5b/pop-to-ebx
22972     5a/pop-to-edx
22973     59/pop-to-ecx
22974     # . epilogue
22975     89/<- %esp 5/r32/ebp
22976     5d/pop-to-ebp
22977     c3/return
22978 
22979 check-mu-return-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
22980     # . prologue
22981     55/push-ebp
22982     89/<- %ebp 4/r32/esp
22983     # . save registers
22984     50/push-eax
22985     51/push-ecx
22986     52/push-edx
22987     53/push-ebx
22988     56/push-esi
22989     57/push-edi
22990     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
22991     81 5/subop/subtract %esp 0x60/imm32
22992     68/push 0x60/imm32/size
22993     68/push 0/imm32/read
22994     68/push 0/imm32/write
22995     89/<- %edx 4/r32/esp
22996     # var template/esi: (addr list var) = fn->outputs
22997     8b/-> *(ebp+0xc) 0/r32/eax
22998     (lookup *(eax+0x10) *(eax+0x14))  # Function-outputs Function-outputs => eax
22999     89/<- %esi 0/r32/eax
23000     # var curr-template/ebx: (addr list var) = fn->outputs
23001     89/<- %ebx 0/r32/eax
23002     # var curr/edi: (addr stmt-var) = stmt->inouts
23003     8b/-> *(ebp+8) 0/r32/eax
23004     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23005     89/<- %edi 0/r32/eax
23006     {
23007       # if template is null, break
23008       81 7/subop/compare %ebx 0/imm32
23009       0f 84/jump-if-= break/disp32
23010       # if curr is null, abort
23011       81 7/subop/compare %edi 0/imm32
23012       0f 84/jump-if-= $check-mu-return-stmt:error-too-few-inouts/disp32
23013       # var template-type/ecx: (addr type-tree) = template->value->type
23014       (lookup *ebx *(ebx+4))  # List-value List-value => eax
23015       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
23016       89/<- %ecx 0/r32/eax
23017       # var curr-type/eax: (addr type-tree) = curr->value->type
23018       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
23019       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
23020       # if (curr->is-deref?) curr-type = payload of curr-type
23021       81 7/subop/compare *(edi+0x10) 0/imm32/false  # Stmt-var-is-deref
23022       {
23023         74/jump-if-= break/disp8
23024         (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
23025         # if t->right is null, t = t->left
23026         81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
23027         75/jump-if-!= break/disp8
23028         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23029       }
23030       # if curr-type is literal and template-type is float, abort
23031       50/push-eax
23032       {
23033         (is-simple-mu-type? %eax 0)  # literal => eax
23034         3d/compare-eax-and 0/imm32/false
23035         74/jump-if-= break/disp8
23036         (is-simple-mu-type? %ecx 0xf)  # float => eax
23037         3d/compare-eax-and 0/imm32/false
23038         0f 85/jump-if-!= $check-mu-return-stmt:error-literal-to-float/disp32
23039       }
23040       58/pop-to-eax
23041       # if (curr-type != template-type) abort
23042       (type-match? %ecx %eax %edx)  # => eax
23043       3d/compare-eax-and 0/imm32/false
23044       0f 84/jump-if-= $check-mu-return-stmt:error1/disp32
23045       # if register-within-list-with-conflict?(curr, original template, curr-template, stmt) abort
23046       (register-within-list-with-conflict? %edi %esi %ebx *(ebp+8))  # => eax
23047       3d/compare-eax-and 0/imm32/false
23048       0f 85/jump-if-!= $check-mu-return-stmt:error2/disp32
23049       # template = template->next
23050       (lookup *(ebx+8) *(ebx+0xc))  # List-next List-next => eax
23051       89/<- %ebx 0/r32/eax
23052       # curr = curr->next
23053       (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
23054       89/<- %edi 0/r32/eax
23055       #
23056       e9/jump loop/disp32
23057     }
23058     # if curr is not null, abort
23059     81 7/subop/compare %edi 0/imm32
23060     0f 85/jump-if-!= $check-mu-return-stmt:error-too-many-inouts/disp32
23061 $check-mu-return-stmt:end:
23062     # . reclaim locals
23063     81 0/subop/add %esp 0x6c/imm32
23064     # . restore registers
23065     5f/pop-to-edi
23066     5e/pop-to-esi
23067     5b/pop-to-ebx
23068     5a/pop-to-edx
23069     59/pop-to-ecx
23070     58/pop-to-eax
23071     # . epilogue
23072     89/<- %esp 5/r32/ebp
23073     5d/pop-to-ebp
23074     c3/return
23075 
23076 $check-mu-return-stmt:error1:
23077     (write-buffered *(ebp+0x10) "fn ")
23078     8b/-> *(ebp+0xc) 0/r32/eax
23079     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23080     (write-buffered *(ebp+0x10) %eax)
23081     (write-buffered *(ebp+0x10) ": return: '")
23082     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
23083     (lookup *eax *(eax+4))  # Var-name Var-name => eax
23084     (write-buffered *(ebp+0x10) %eax)
23085     (write-buffered *(ebp+0x10) "' has the wrong type\n")
23086     (flush *(ebp+0x10))
23087     (stop *(ebp+0x14) 1)
23088     # never gets here
23089 
23090 $check-mu-return-stmt:error2:
23091     (write-buffered *(ebp+0x10) "fn ")
23092     8b/-> *(ebp+0xc) 0/r32/eax
23093     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23094     (write-buffered *(ebp+0x10) %eax)
23095     (write-buffered *(ebp+0x10) ": return: '")
23096     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
23097     (lookup *eax *(eax+4))  # Var-name Var-name => eax
23098     (write-buffered *(ebp+0x10) %eax)
23099     (write-buffered *(ebp+0x10) "' is no longer available\n")
23100     (flush *(ebp+0x10))
23101     (stop *(ebp+0x14) 1)
23102     # never gets here
23103 
23104 $check-mu-return-stmt:error-literal-to-float:
23105     (write-buffered *(ebp+0x10) "fn ")
23106     8b/-> *(ebp+0xc) 0/r32/eax
23107     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23108     (write-buffered *(ebp+0x10) %eax)
23109     (write-buffered *(ebp+0x10) ": return: cannot copy literal '")
23110     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
23111     (lookup *eax *(eax+4))  # Var-name Var-name => eax
23112     (write-buffered *(ebp+0x10) %eax)
23113     (write-buffered *(ebp+0x10) "' to float\n")
23114     (flush *(ebp+0x10))
23115     (stop *(ebp+0x14) 1)
23116     # never gets here
23117 
23118 $check-mu-return-stmt:error-too-few-inouts:
23119     (write-buffered *(ebp+0x10) "fn ")
23120     8b/-> *(ebp+0xc) 0/r32/eax
23121     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23122     (write-buffered *(ebp+0x10) %eax)
23123     (write-buffered *(ebp+0x10) ": return: too few inouts\n")
23124     (flush *(ebp+0x10))
23125     (stop *(ebp+0x14) 1)
23126     # never gets here
23127 
23128 $check-mu-return-stmt:error-too-many-inouts:
23129     (write-buffered *(ebp+0x10) "fn ")
23130     8b/-> *(ebp+0xc) 0/r32/eax
23131     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23132     (write-buffered *(ebp+0x10) %eax)
23133     (write-buffered *(ebp+0x10) ": return: too many inouts\n")
23134     (flush *(ebp+0x10))
23135     (stop *(ebp+0x14) 1)
23136     # never gets here
23137 
23138 check-all-unique-registers:  # outputs: (addr list var), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
23139     # . prologue
23140     55/push-ebp
23141     89/<- %ebp 4/r32/esp
23142     # . save registers
23143     50/push-eax
23144     51/push-ecx
23145     56/push-esi
23146     # var table/esi: (addr table (handle array byte) int 8)
23147     81 5/subop/subtract %esp 0x60/imm32
23148     68/push 0x60/imm32/size
23149     68/push 0/imm32/read
23150     68/push 0/imm32/write
23151     89/<- %esi 4/r32/esp
23152     # var curr/ecx: (addr list var) = outputs
23153     8b/-> *(ebp+8) 1/r32/ecx
23154     {
23155       # if (curr == 0) break
23156       81 7/subop/compare %ecx 0/imm32
23157       0f 84/jump-if-= break/disp32
23158       # var reg/eax: (addr array byte) = curr->value->register  # guaranteed to exist
23159       (lookup *ecx *(ecx+4))  # List-value List-value => eax
23160       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
23161       # if reg exists in table, abort
23162       (maybe-get %esi %eax 0xc)  # => eax
23163       3d/compare-eax-and 0/imm32
23164       0f 85/jump-if-!= $check-all-unique-registers:abort/disp32
23165       # insert reg in table
23166       (lookup *ecx *(ecx+4))  # List-value List-value => eax
23167       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
23168       (get-or-insert %esi %eax 0xc Heap)
23169       # curr = curr->next
23170       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
23171       89/<- %ecx 0/r32/eax
23172       e9/jump loop/disp32
23173     }
23174 $check-all-unique-registers:end:
23175     # . reclaim locals
23176     81 0/subop/add %esp 0x6c/imm32
23177     # . restore registers
23178     5e/pop-to-esi
23179     59/pop-to-ecx
23180     58/pop-to-eax
23181     # . epilogue
23182     89/<- %esp 5/r32/ebp
23183     5d/pop-to-ebp
23184     c3/return
23185 
23186 $check-all-unique-registers:abort:
23187     (write-buffered *(ebp+0x10) "fn ")
23188     8b/-> *(ebp+0xc) 0/r32/eax
23189     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23190     (write-buffered *(ebp+0x10) %eax)
23191     (write-buffered *(ebp+0x10) ": outputs must be in unique registers\n")
23192     (flush *(ebp+0x10))
23193     (stop *(ebp+0x14) 1)
23194     # never gets here
23195 
23196 # return false if s's register is not between start (inclusive) and end (exclusive)
23197 # return false if the positionally corresponding register in stmt->inouts (where s comes from) is also s's register
23198 # otherwise return true
23199 register-within-list-with-conflict?:  # s: (addr stmt-var), start: (addr list var), end: (addr list var), stmt: (addr stmt) -> result/eax: boolean
23200     # . prologue
23201     55/push-ebp
23202     89/<- %ebp 4/r32/esp
23203     # . save registers
23204     51/push-ecx
23205     52/push-edx
23206     53/push-ebx
23207     56/push-esi
23208     57/push-edi
23209     # var target/ebx: (addr array byte) = s->value->register
23210     8b/-> *(ebp+8) 0/r32/eax
23211     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
23212     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
23213 #?     (write-buffered Stderr "AA: ")
23214 #?     (write-buffered Stderr %eax)
23215 #?     (write-buffered Stderr Newline)
23216 #?     (flush Stderr)
23217     # if (var->register == 0) return false
23218     3d/compare-eax-and 0/imm32
23219     0f 84/jump-if-= $register-within-list-with-conflict?:end/disp32  # eax turns into result
23220     89/<- %ebx 0/r32/eax
23221     # var curr/ecx: (addr list var) = start
23222     8b/-> *(ebp+0xc) 1/r32/ecx
23223     # edx = end
23224     8b/-> *(ebp+0x10) 2/r32/edx
23225     {
23226       # if (curr == 0) break
23227       81 7/subop/compare %edi 0/imm32
23228       0f 84/jump-if-= break/disp32
23229       # if (curr == end) break
23230       39/compare %ecx 2/r32/edx
23231       0f 84/jump-if-= break/disp32
23232       # var curr-reg/eax: (addr array byte) = curr->value->register
23233       (lookup *ecx *(ecx+4))  # List-value List-value => eax
23234       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
23235       # if (curr-reg == 0) continue
23236       3d/compare-eax-and 0/imm32
23237       74/jump-if-= $register-within-list-with-conflict?:continue/disp8
23238       # if (curr-reg == target) check for conflict
23239       (string-equal? %eax %ebx)  # => eax
23240       3d/compare-eax-and 0/imm32/false
23241       {
23242         74/jump-if-= break/disp8
23243 #?         (write-buffered Stderr "conflict?\n")
23244 #?         (flush Stderr)
23245         # var return-inouts/eax: (addr stmt-var) = stmt->inouts
23246         8b/-> *(ebp+0x14) 0/r32/eax
23247         (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23248         (register-conflict? %ebx %eax *(ebp+0xc))  # => eax
23249         eb/jump $register-within-list-with-conflict?:end/disp8
23250       }
23251 $register-within-list-with-conflict?:continue:
23252       # curr = curr->next
23253       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
23254       89/<- %ecx 0/r32/eax
23255       e9/jump loop/disp32
23256     }
23257     # return false
23258     b8/copy-to-eax 0/imm32/false
23259 $register-within-list-with-conflict?:end:
23260     # . restore registers
23261     5f/pop-to-edi
23262     5e/pop-to-esi
23263     5b/pop-to-ebx
23264     5a/pop-to-edx
23265     59/pop-to-ecx
23266     # . epilogue
23267     89/<- %esp 5/r32/ebp
23268     5d/pop-to-ebp
23269     c3/return
23270 
23271 # At the first occurrence of register 'reg' in fn-outputs,
23272 # check if the corresponding element of return-inouts has a different register.
23273 # This hacky helper is intended to be called in one specific place. Don't
23274 # reuse it as is.
23275 register-conflict?:  # reg: (addr array byte), return-inouts: (addr stmt-var), fn-outputs: (addr list var) => result/eax: boolean
23276     # . prologue
23277     55/push-ebp
23278     89/<- %ebp 4/r32/esp
23279     # . save registers
23280     51/push-ecx
23281     52/push-edx
23282     53/push-ebx
23283     56/push-esi
23284     57/push-edi
23285 #?     (write-buffered Stderr "BB: ")
23286 #?     (write-buffered Stderr *(ebp+8))
23287 #?     (write-buffered Stderr Newline)
23288 #?     (flush Stderr)
23289     # var curr-output/edi: (addr list var) = fn-outputs
23290     8b/-> *(ebp+0x10) 7/r32/edi
23291     # var curr-inout/esi: (addr stmt-var) = return-inouts
23292     8b/-> *(ebp+0xc) 6/r32/esi
23293     {
23294       # if (curr-output == 0) abort
23295       81 7/subop/compare %edi 0/imm32
23296       0f 84/jump-if-= break/disp32
23297       # if (curr-output->value->register != reg) continue
23298       (lookup *edi *(edi+4))  # List-value List-value => eax
23299       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
23300       (string-equal? %eax *(ebp+8))  # => eax
23301       3d/compare-eax-and 0/imm32/false
23302       0f 84/jump-if= $register-conflict?:continue/disp32
23303 #?       (write-buffered Stderr "rescan\n")
23304 #?       (flush Stderr)
23305       # var curr-reg/eax: (addr array byte) = curr-inout->value->register
23306       (lookup *esi *(esi+4))  # List-value List-value => eax
23307       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
23308       # if (curr-reg == 0) return true
23309       3d/compare-eax-and 0/imm32
23310       {
23311         75/jump-if-!= break/disp8
23312 #?         (write-buffered Stderr "no register\n")
23313 #?         (flush Stderr)
23314         b8/copy-to-eax 1/imm32/true
23315         e9/jump $register-conflict?:end/disp32
23316       }
23317       # return (curr-reg != reg)
23318       (string-equal? %eax *(ebp+8))  # => eax
23319       3d/compare-eax-and 0/imm32/false
23320       0f 94/set-if-= %al
23321 #?       (write-buffered Stderr "final: ")
23322 #?       (write-int32-hex-buffered Stderr %eax)
23323 #?       (write-buffered Stderr Newline)
23324 #?       (flush Stderr)
23325       eb/jump $register-conflict?:end/disp8
23326 $register-conflict?:continue:
23327       # curr-output = curr-output->next
23328       (lookup *(edi+8) *(edi+0xc))  # List-next List-next => eax
23329       89/<- %edi 0/r32/eax
23330       # curr-inout = curr-inout->next
23331       (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
23332       89/<- %esi 0/r32/eax
23333       e9/jump loop/disp32
23334     }
23335     # should never get here
23336     (write-buffered Stderr "register-conflict? misused\n")
23337     (flush Stderr)
23338     e8/call syscall_exit/disp32
23339 $register-conflict?:end:
23340     # . restore registers
23341     5f/pop-to-edi
23342     5e/pop-to-esi
23343     5b/pop-to-ebx
23344     5a/pop-to-edx
23345     59/pop-to-ecx
23346     # . epilogue
23347     89/<- %esp 5/r32/ebp
23348     5d/pop-to-ebp
23349     c3/return
23350 
23351 check-final-stmt-is-return:  # block: (addr block), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
23352     # . prologue
23353     55/push-ebp
23354     89/<- %ebp 4/r32/esp
23355     # . save registers
23356     50/push-eax
23357     51/push-ecx
23358     # var curr/ecx: (addr list stmt) = block->stmts
23359     8b/-> *(ebp+8) 0/r32/eax
23360     (lookup *(eax+4) *(eax+8))  # Block-stmts Block-stmts => eax
23361     3d/compare-eax-and 0/imm32
23362     74/jump-if-= $check-final-stmt-is-return:error/disp8
23363     89/<- %ecx 0/r32/eax
23364     {
23365       # if curr->next == 0, break
23366       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
23367       3d/compare-eax-and 0/imm32
23368       74/jump-if-= break/disp8
23369       # curr = curr->next
23370       89/<- %ecx 0/r32/eax
23371       e9/jump loop/disp32
23372     }
23373 $check-final-stmt-is-return:check-tag:
23374     # if curr->value->tag != Stmt1, abort
23375     (lookup *ecx *(ecx+4))  # List-value List-value => eax
23376     81 7/subop/compare *eax 1/imm32/stmt1  # Stmt-tag
23377     75/jump-if-!= $check-final-stmt-is-return:error/disp8
23378 $check-final-stmt-is-return:check-operation:
23379     # if curr->operation != "return", abort
23380     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
23381     (string-equal? %eax "return")
23382     3d/compare-eax-and 0/imm32/false
23383     74/jump-if-= $check-final-stmt-is-return:error/disp8
23384 $check-final-stmt-is-return:end:
23385     # . restore registers
23386     59/pop-to-ecx
23387     58/pop-to-eax
23388     # . epilogue
23389     89/<- %esp 5/r32/ebp
23390     5d/pop-to-ebp
23391     c3/return
23392 
23393 $check-final-stmt-is-return:error:
23394     (write-buffered *(ebp+0x10) "fn ")
23395     8b/-> *(ebp+0xc) 0/r32/eax
23396     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23397     (write-buffered *(ebp+0x10) %eax)
23398     (write-buffered *(ebp+0x10) ": final statement should be a 'return'\n")
23399     (flush *(ebp+0x10))
23400     (stop *(ebp+0x14) 1)
23401     # never gets here
23402 
23403 check-no-breaks:  # block: (addr block), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
23404     # . prologue
23405     55/push-ebp
23406     89/<- %ebp 4/r32/esp
23407     # . save registers
23408     50/push-eax
23409     51/push-ecx
23410     # var curr/ecx: (addr list stmt) = block->stmts
23411     8b/-> *(ebp+8) 0/r32/eax
23412     (lookup *(eax+4) *(eax+8))  # Block-stmts Block-stmts => eax
23413     3d/compare-eax-and 0/imm32
23414     0f 84/jump-if-= $check-no-breaks:end/disp32
23415     89/<- %ecx 0/r32/eax
23416     {
23417       # if curr->next == 0, break
23418       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
23419       3d/compare-eax-and 0/imm32
23420       74/jump-if-= break/disp8
23421       # if curr->value->tag != Stmt1, continue
23422       (lookup *ecx *(ecx+4))  # List-value List-value => eax
23423       81 7/subop/compare *eax 1/imm32/stmt1  # Stmt-tag
23424       75/jump-if-!= $check-no-breaks:continue/disp8
23425       # if curr->value->operation starts with "break", abort
23426       (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
23427       (string-starts-with? %eax "break")  # => eax
23428       3d/compare-eax-and 0/imm32/false
23429       75/jump-if-!= $check-no-breaks:error/disp8
23430 $check-no-breaks:continue:
23431       # curr = curr->next
23432       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
23433       89/<- %ecx 0/r32/eax
23434       e9/jump loop/disp32
23435     }
23436 $check-no-breaks:end:
23437     # . restore registers
23438     59/pop-to-ecx
23439     58/pop-to-eax
23440     # . epilogue
23441     89/<- %esp 5/r32/ebp
23442     5d/pop-to-ebp
23443     c3/return
23444 
23445 $check-no-breaks:error:
23446     (write-buffered *(ebp+0x10) "fn ")
23447     8b/-> *(ebp+0xc) 0/r32/eax
23448     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23449     (write-buffered *(ebp+0x10) %eax)
23450     (write-buffered *(ebp+0x10) " has outputs, so you cannot 'break' out of the outermost block. Use 'return'.\n")
23451     (flush *(ebp+0x10))
23452     (stop *(ebp+0x14) 1)
23453     # never gets here
23454 
23455 check-mu-get-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
23456     # . prologue
23457     55/push-ebp
23458     89/<- %ebp 4/r32/esp
23459     # . save registers
23460     50/push-eax
23461     51/push-ecx
23462     52/push-edx
23463     53/push-ebx
23464     56/push-esi
23465     57/push-edi
23466     # esi = stmt
23467     8b/-> *(ebp+8) 6/r32/esi
23468     # - check for 0 inouts
23469     # var base/ecx: (addr var) = stmt->inouts->value
23470     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23471     3d/compare-eax-and 0/imm32/false
23472     0f 84/jump-if-= $check-mu-get-stmt:error-too-few-inouts/disp32
23473     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
23474     89/<- %ecx 0/r32/eax
23475 $check-mu-get-stmt:check-base:
23476     # - check base type
23477     # if it's an 'addr', check that it's in a register
23478     # var base-type/ebx: (addr type-tree) = lookup(base->type)
23479     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
23480     89/<- %ebx 0/r32/eax
23481     {
23482       81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
23483       0f 85/jump-if-!= break/disp32
23484 $check-mu-get-stmt:base-is-compound:
23485       # if (type->left != addr) break
23486       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
23487       (is-simple-mu-type? %eax 2)  # addr => eax
23488       3d/compare-eax-and 0/imm32/false
23489       74/jump-if-= break/disp8
23490 $check-mu-get-stmt:base-is-addr:
23491       # now check for register
23492       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
23493       0f 84/jump-if-= $check-mu-get-stmt:error-base-type-addr-but-not-register/disp32
23494 $check-mu-get-stmt:base-is-addr-in-register:
23495       # type->left is now an addr; skip it
23496       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
23497       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
23498       0f 85/jump-if-!= $check-mu-get-stmt:error-bad-base/disp32
23499 $check-mu-get-stmt:base-is-addr-to-atom-in-register:
23500       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23501       89/<- %ebx 0/r32/eax
23502     }
23503 $check-mu-get-stmt:check-base-typeinfo:
23504     # ensure type is a container
23505     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
23506     {
23507       75/jump-if-!= break/disp8
23508       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
23509       89/<- %ebx 0/r32/eax
23510     }
23511     # var base-type-id/ebx: type-id = base-type->value
23512     8b/-> *(ebx+4) 3/r32/ebx  # Type-tree-value
23513     (is-container? %ebx)  # => eax
23514     3d/compare-eax-and 0/imm32/false
23515     0f 84/jump-if-= $check-mu-get-stmt:error-bad-base/disp32
23516     # var base-typeinfo/edx: (addr typeinfo) = find-typeinfo(base-type-id)
23517     # . var container/ecx: (handle typeinfo)
23518     68/push 0/imm32
23519     68/push 0/imm32
23520     89/<- %ecx 4/r32/esp
23521     # .
23522     (find-typeinfo %ebx %ecx)
23523     (lookup *ecx *(ecx+4))  # => eax
23524     # . reclaim container
23525     81 0/subop/add %esp 8/imm32
23526     # .
23527     89/<- %edx 0/r32/eax
23528     # var offset/ecx: (addr stmt-var) = stmt->inouts->next
23529     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23530     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
23531     89/<- %ecx 0/r32/eax
23532     # - check for 1 inout
23533     3d/compare-eax-and 0/imm32/false
23534     0f 84/jump-if-= $check-mu-get-stmt:error-too-few-inouts/disp32
23535     # var offset/ecx: (addr var) = lookup(offset->value)
23536     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
23537     89/<- %ecx 0/r32/eax
23538     # - check for valid field
23539     81 7/subop/compare *(ecx+0x14) -1/imm32/uninitialized  # Var-offset
23540     0f 84/jump-if-= $check-mu-get-stmt:error-bad-field/disp32
23541     # - check for too many inouts
23542     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23543     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
23544     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
23545     3d/compare-eax-and 0/imm32/false
23546     0f 85/jump-if-!= $check-mu-get-stmt:error-too-many-inouts/disp32
23547     # var output/edi: (addr var) = stmt->outputs->value
23548     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
23549     # - check for 0 outputs
23550     3d/compare-eax-and 0/imm32/false
23551     0f 84/jump-if-= $check-mu-get-stmt:error-too-few-outputs/disp32
23552     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
23553     89/<- %edi 0/r32/eax
23554 $check-mu-get-stmt:check-output-type:
23555     # - check output type
23556     # must be in register
23557     (lookup *(edi+0x18) *(edi+0x1c))  # Var-register Var-register => eax
23558     3d/compare-eax-and 0/imm32
23559     0f 84/jump-if-= $check-mu-get-stmt:error-output-not-in-register/disp32
23560     # must have a non-atomic type
23561     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
23562     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
23563     0f 85/jump-if-!= $check-mu-get-stmt:error-output-type-not-address/disp32
23564     # type must start with (addr ...)
23565     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23566     (is-simple-mu-type? %eax 2)  # => eax
23567     3d/compare-eax-and 0/imm32/false
23568     0f 84/jump-if-= $check-mu-get-stmt:error-output-type-not-address/disp32
23569 $check-mu-get-stmt:check-output-type-match:
23570     # payload of addr type must match 'type' definition
23571     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
23572     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
23573     # if (payload->right == null) payload = payload->left
23574     81 7/subop/compare *(eax+0xc) 0/imm32/null  # Type-tree-right
23575     {
23576       75/jump-if-!= break/disp8
23577       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23578     }
23579     89/<- %edi 0/r32/eax
23580     # . var output-name/ecx: (addr array byte)
23581     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
23582     89/<- %ecx 0/r32/eax
23583     # . var base-typeinfo-entry/eax: (addr handle typeinfo-entry)
23584     (lookup *(edx+4) *(edx+8))  # Typeinfo-fields Typeinfo-fields => eax
23585     (get %eax %ecx 0x10)  # => eax
23586     # .
23587     (lookup *eax *(eax+4))  # => eax
23588     (lookup *eax *(eax+4))  # Typeinfo-entry-input-var Typeinfo-entry-input-var => eax
23589     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
23590     # .
23591     (type-equal? %edi %eax)  # => eax
23592     3d/compare-eax-and 0/imm32/false
23593     0f 84/jump-if-= $check-mu-get-stmt:error-bad-output-type/disp32
23594     # - check for too many outputs
23595     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
23596     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
23597     3d/compare-eax-and 0/imm32/false
23598     0f 85/jump-if-!= $check-mu-get-stmt:error-too-many-outputs/disp32
23599 $check-mu-get-stmt:end:
23600     # . restore registers
23601     5f/pop-to-edi
23602     5e/pop-to-esi
23603     5b/pop-to-ebx
23604     5a/pop-to-edx
23605     59/pop-to-ecx
23606     58/pop-to-eax
23607     # . epilogue
23608     89/<- %esp 5/r32/ebp
23609     5d/pop-to-ebp
23610     c3/return
23611 
23612 $check-mu-get-stmt:error-too-few-inouts:
23613     (write-buffered *(ebp+0x10) "fn ")
23614     8b/-> *(ebp+0xc) 0/r32/eax
23615     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23616     (write-buffered *(ebp+0x10) %eax)
23617     (write-buffered *(ebp+0x10) ": stmt get: too few inouts (2 required)\n")
23618     (flush *(ebp+0x10))
23619     (stop *(ebp+0x14) 1)
23620     # never gets here
23621 
23622 $check-mu-get-stmt:error-too-many-inouts:
23623     (write-buffered *(ebp+0x10) "fn ")
23624     8b/-> *(ebp+0xc) 0/r32/eax
23625     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23626     (write-buffered *(ebp+0x10) %eax)
23627     (write-buffered *(ebp+0x10) ": stmt get: too many inouts (2 required)\n")
23628     (flush *(ebp+0x10))
23629     (stop *(ebp+0x14) 1)
23630     # never gets here
23631 
23632 $check-mu-get-stmt:error-too-few-outputs:
23633     (write-buffered *(ebp+0x10) "fn ")
23634     8b/-> *(ebp+0xc) 0/r32/eax
23635     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23636     (write-buffered *(ebp+0x10) %eax)
23637     (write-buffered *(ebp+0x10) ": stmt get: must have an output\n")
23638     (flush *(ebp+0x10))
23639     (stop *(ebp+0x14) 1)
23640     # never gets here
23641 
23642 $check-mu-get-stmt:error-too-many-outputs:
23643     (write-buffered *(ebp+0x10) "fn ")
23644     8b/-> *(ebp+0xc) 0/r32/eax
23645     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23646     (write-buffered *(ebp+0x10) %eax)
23647     (write-buffered *(ebp+0x10) ": stmt get: too many outputs (1 required)\n")
23648     (flush *(ebp+0x10))
23649     (stop *(ebp+0x14) 1)
23650     # never gets here
23651 
23652 $check-mu-get-stmt:error-bad-base:
23653     # error("fn " fn ": stmt get: var '" base->name "' must have a 'type' definition\n")
23654     (write-buffered *(ebp+0x10) "fn ")
23655     8b/-> *(ebp+0xc) 0/r32/eax
23656     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23657     (write-buffered *(ebp+0x10) %eax)
23658     (write-buffered *(ebp+0x10) ": stmt get: var '")
23659     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23660     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
23661     (lookup *eax *(eax+4))  # Var-name Var-name => eax
23662     (write-buffered *(ebp+0x10) %eax)
23663     (write-buffered *(ebp+0x10) "' must have a 'type' definition\n")
23664     (flush *(ebp+0x10))
23665     (stop *(ebp+0x14) 1)
23666     # never gets here
23667 
23668 $check-mu-get-stmt:error-base-type-addr-but-not-register:
23669     (write-buffered *(ebp+0x10) "fn ")
23670     8b/-> *(ebp+0xc) 0/r32/eax
23671     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23672     (write-buffered *(ebp+0x10) %eax)
23673     (write-buffered *(ebp+0x10) ": stmt get: var '")
23674     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23675     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
23676     (lookup *eax *(eax+4))  # Var-name Var-name => eax
23677     (write-buffered *(ebp+0x10) %eax)
23678     (write-buffered *(ebp+0x10) "' is an 'addr' type, and so must live in a register\n")
23679     (flush *(ebp+0x10))
23680     (stop *(ebp+0x14) 1)
23681     # never gets here
23682 
23683 $check-mu-get-stmt:error-bad-field:
23684     # error("fn " fn ": stmt get: type " type " has no member called '" curr->name "'\n")
23685     (write-buffered *(ebp+0x10) "fn ")
23686     8b/-> *(ebp+0xc) 0/r32/eax
23687     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23688     (write-buffered *(ebp+0x10) %eax)
23689     (write-buffered *(ebp+0x10) ": stmt get: type '")
23690     # . write(Type-id->data[tmp])
23691     bf/copy-to-edi Type-id/imm32
23692     8b/-> *(edi+ebx<<2+0xc) 6/r32/esi
23693     {
23694       81 7/subop/compare %esi 0/imm32
23695       74/jump-if-= break/disp8
23696       (write-buffered *(ebp+0x10) %esi)
23697     }
23698     # .
23699     (write-buffered *(ebp+0x10) "' has no member called '")
23700     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
23701     (write-buffered *(ebp+0x10) %eax)
23702     (write-buffered *(ebp+0x10) "'\n")
23703     (flush *(ebp+0x10))
23704     (stop *(ebp+0x14) 1)
23705     # never gets here
23706 
23707 $check-mu-get-stmt:error-output-not-in-register:
23708     (write-buffered *(ebp+0x10) "fn ")
23709     8b/-> *(ebp+0xc) 0/r32/eax
23710     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23711     (write-buffered *(ebp+0x10) %eax)
23712     (write-buffered *(ebp+0x10) ": stmt get: output '")
23713     (lookup *edi *(edi+4))  # Var-name Var-name => eax
23714     (write-buffered *(ebp+0x10) %eax)
23715     (write-buffered *(ebp+0x10) "' is not in a register\n")
23716     (flush *(ebp+0x10))
23717     (stop *(ebp+0x14) 1)
23718     # never gets here
23719 
23720 $check-mu-get-stmt:error-output-type-not-address:
23721     (write-buffered *(ebp+0x10) "fn ")
23722     8b/-> *(ebp+0xc) 0/r32/eax
23723     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23724     (write-buffered *(ebp+0x10) %eax)
23725     (write-buffered *(ebp+0x10) ": stmt get: output must be an addr\n")
23726     (flush *(ebp+0x10))
23727     (stop *(ebp+0x14) 1)
23728     # never gets here
23729 
23730 $check-mu-get-stmt:error-bad-output-type:
23731     (write-buffered *(ebp+0x10) "fn ")
23732     8b/-> *(ebp+0xc) 0/r32/eax
23733     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23734     (write-buffered *(ebp+0x10) %eax)
23735     (write-buffered *(ebp+0x10) ": stmt get: wrong output type for member '")
23736     (write-buffered *(ebp+0x10) %ecx)
23737     (write-buffered *(ebp+0x10) "' of type '")
23738     bf/copy-to-edi Type-id/imm32
23739     8b/-> *(edi+ebx<<2+0xc) 6/r32/esi
23740     {
23741       81 7/subop/compare %esi 0/imm32
23742       74/jump-if-= break/disp8
23743       (write-buffered *(ebp+0x10) %esi)
23744     }
23745     (write-buffered *(ebp+0x10) "'\n")
23746     (flush *(ebp+0x10))
23747     (stop *(ebp+0x14) 1)
23748     # never gets here
23749 
23750 check-mu-index-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
23751     # . prologue
23752     55/push-ebp
23753     89/<- %ebp 4/r32/esp
23754     # . save registers
23755     50/push-eax
23756     51/push-ecx
23757     52/push-edx
23758     53/push-ebx
23759     56/push-esi
23760     57/push-edi
23761     # esi = stmt
23762     8b/-> *(ebp+8) 6/r32/esi
23763     # - check for 0 inouts
23764     # var base/ecx: (addr var) = stmt->inouts->value
23765     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23766 $check-mu-index-stmt:check-no-inouts:
23767     3d/compare-eax-and 0/imm32
23768     0f 84/jump-if-= $check-mu-index-stmt:error-too-few-inouts/disp32
23769     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
23770     89/<- %ecx 0/r32/eax
23771     # - check base type is either (addr array ...) in register or (array ...) on stack
23772     # var base-type/ebx: (addr type-tree) = lookup(base->type)
23773     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
23774     89/<- %ebx 0/r32/eax
23775     # if base-type is an atom, abort with a precise error
23776     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
23777     {
23778       74/jump-if-= break/disp8
23779       (is-simple-mu-type? %ebx 3)  # array => eax
23780       3d/compare-eax-and 0/imm32/false
23781       0f 85/jump-if-!= $check-mu-index-stmt:error-base-array-atom-type/disp32
23782       0f 84/jump-if-= $check-mu-index-stmt:error-base-non-array-type/disp32
23783     }
23784 $check-mu-index-stmt:base-is-compound:
23785     # if type->left not addr or array, abort
23786     {
23787       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
23788       (is-simple-mu-type? %eax 2)  # addr => eax
23789       3d/compare-eax-and 0/imm32/false
23790       75/jump-if-!= break/disp8
23791       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
23792       (is-simple-mu-type? %eax 3)  # array => eax
23793       3d/compare-eax-and 0/imm32/false
23794       75/jump-if-!= break/disp8
23795       e9/jump $check-mu-index-stmt:error-base-non-array-type/disp32
23796     }
23797     # if (type->left == addr) ensure type->right->left == array and type->register exists
23798     {
23799       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
23800       (is-simple-mu-type? %eax 2)  # addr => eax
23801       3d/compare-eax-and 0/imm32/false
23802       74/jump-if-= break/disp8
23803 $check-mu-index-stmt:base-is-addr:
23804       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
23805       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23806       (is-simple-mu-type? %eax 3)  # array => eax
23807       3d/compare-eax-and 0/imm32/false
23808       0f 84/jump-if-= $check-mu-index-stmt:error-base-non-array-type/disp32
23809 $check-mu-index-stmt:check-base-addr-is-register:
23810       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
23811       0f 84/jump-if-= $check-mu-index-stmt:error-base-address-array-type-on-stack/disp32
23812     }
23813     # if (type->left == array) ensure type->register doesn't exist
23814     {
23815       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
23816       (is-simple-mu-type? %eax 3)  # array => eax
23817       3d/compare-eax-and 0/imm32/false
23818       74/jump-if-= break/disp8
23819 $check-mu-index-stmt:base-is-array:
23820       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
23821       0f 85/jump-if-!= $check-mu-index-stmt:error-base-array-type-in-register/disp32
23822     }
23823     # if (base-type->left == addr) base-type = base-type->right
23824     {
23825       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
23826       (is-simple-mu-type? %eax 2)  # addr => eax
23827       3d/compare-eax-and 0/imm32/false
23828       74/jump-if-= break/disp8
23829       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
23830       89/<- %ebx 0/r32/eax
23831     }
23832     # - check for 1 inout
23833     # var index/ecx: (addr stmt-var) = stmt->inouts->next->value
23834     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23835     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
23836 $check-mu-index-stmt:check-single-inout:
23837     3d/compare-eax-and 0/imm32
23838     0f 84/jump-if-= $check-mu-index-stmt:error-too-few-inouts/disp32
23839     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
23840     89/<- %ecx 0/r32/eax
23841     # - check index is either a literal or register
23842     # var index-type/edx: (addr type-tree)
23843     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
23844     89/<- %edx 0/r32/eax
23845     # if index type is an atom, it must be a literal or int
23846     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
23847     {
23848       74/jump-if-= break/disp8
23849 $check-mu-index-stmt:index-type-is-atom:
23850       (is-simple-mu-type? %edx 0)  # literal => eax
23851       3d/compare-eax-and 0/imm32/false
23852       75/jump-if-!= $check-mu-index-stmt:index-type-done/disp8
23853       (is-simple-mu-type? %edx 1)  # int => eax
23854       3d/compare-eax-and 0/imm32/false
23855       75/jump-if-!= $check-mu-index-stmt:index-type-done/disp8
23856       (is-simple-mu-type? %edx 7)  # offset => eax
23857       3d/compare-eax-and 0/imm32/false
23858       0f 85/jump-if-!= $check-mu-index-stmt:error-index-offset-atom-type/disp32
23859       e9/jump $check-mu-index-stmt:error-invalid-index-type/disp32
23860     }
23861     # if index type is a non-atom: it must be an offset
23862     {
23863       75/jump-if-!= break/disp8
23864 $check-mu-index-stmt:index-type-is-non-atom:
23865       (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
23866       (is-simple-mu-type? %eax 7)  # offset => eax
23867       3d/compare-eax-and 0/imm32/false
23868       0f 84/jump-if-= $check-mu-index-stmt:error-invalid-index-type/disp32
23869     }
23870 $check-mu-index-stmt:index-type-done:
23871     # check index is either a literal or in a register
23872     {
23873       (is-simple-mu-type? %edx 0)  # literal => eax
23874       3d/compare-eax-and 0/imm32/false
23875       75/jump-if-!= break/disp8
23876 $check-mu-index-stmt:check-index-in-register:
23877       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
23878       0f 84/jump-if-= $check-mu-index-stmt:error-index-on-stack/disp32
23879     }
23880     # - if index is an 'int', check that element type of base has size 1, 2, 4 or 8 bytes.
23881     {
23882       (is-simple-mu-type? %edx 1)  # int => eax
23883       3d/compare-eax-and 0/imm32/false
23884       74/jump-if-= break/disp8
23885 $check-mu-index-stmt:check-index-can-be-int:
23886       (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23887       (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
23888       (array-element-size %eax)  # => eax
23889       3d/compare-eax-and 1/imm32
23890       74/jump-if-= break/disp8
23891       3d/compare-eax-and 2/imm32
23892       74/jump-if-= break/disp8
23893       3d/compare-eax-and 4/imm32
23894       74/jump-if-= break/disp8
23895       3d/compare-eax-and 8/imm32
23896       74/jump-if-= break/disp8
23897       e9/jump $check-mu-index-stmt:error-index-needs-offset/disp32
23898     }
23899     # - check for too many inouts
23900     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23901     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
23902     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
23903     3d/compare-eax-and 0/imm32/false
23904     0f 85/jump-if-!= $check-mu-index-stmt:error-too-many-inouts/disp32
23905     # - check for 0 outputs
23906     # var output/edi: (addr var) = stmt->outputs->value
23907     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
23908     3d/compare-eax-and 0/imm32/false
23909     0f 84/jump-if-= $check-mu-index-stmt:error-too-few-outputs/disp32
23910     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
23911     89/<- %edi 0/r32/eax
23912     # - check output type
23913     # must have a non-atomic type
23914     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
23915     89/<- %edx 0/r32/eax
23916     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
23917     0f 85/jump-if-!= $check-mu-index-stmt:error-output-type-not-address/disp32
23918     # type must start with (addr ...)
23919     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
23920     (is-simple-mu-type? %eax 2)  # addr => eax
23921     3d/compare-eax-and 0/imm32/false
23922     0f 84/jump-if-= $check-mu-index-stmt:error-output-type-not-address/disp32
23923     # if tail(base-type) != tail(output-type) abort
23924     (type-tail %ebx)  # => eax
23925     89/<- %ebx 0/r32/eax
23926     (type-tail %edx)  # => eax
23927     (type-equal? %ebx %eax)  # => eax
23928     3d/compare-eax-and 0/imm32/false
23929     0f 84/jump-if-= $check-mu-index-stmt:error-bad-output-type/disp32
23930     # - check for too many outputs
23931     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
23932     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
23933     3d/compare-eax-and 0/imm32/false
23934     0f 85/jump-if-!= $check-mu-index-stmt:error-too-many-outputs/disp32
23935 $check-mu-index-stmt:end:
23936     # . restore registers
23937     5f/pop-to-edi
23938     5e/pop-to-esi
23939     5b/pop-to-ebx
23940     5a/pop-to-edx
23941     59/pop-to-ecx
23942     58/pop-to-eax
23943     # . epilogue
23944     89/<- %esp 5/r32/ebp
23945     5d/pop-to-ebp
23946     c3/return
23947 
23948 $check-mu-index-stmt:error-base-non-array-type:
23949     (write-buffered *(ebp+0x10) "fn ")
23950     8b/-> *(ebp+0xc) 0/r32/eax
23951     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23952     (write-buffered *(ebp+0x10) %eax)
23953     (write-buffered *(ebp+0x10) ": stmt index: var '")
23954     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
23955     (write-buffered *(ebp+0x10) %eax)
23956     (write-buffered *(ebp+0x10) "' is not an array\n")
23957     (flush *(ebp+0x10))
23958     (stop *(ebp+0x14) 1)
23959     # never gets here
23960 
23961 $check-mu-index-stmt:error-base-array-atom-type:
23962     (write-buffered *(ebp+0x10) "fn ")
23963     8b/-> *(ebp+0xc) 0/r32/eax
23964     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23965     (write-buffered *(ebp+0x10) %eax)
23966     (write-buffered *(ebp+0x10) ": stmt index: array '")
23967     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
23968     (write-buffered *(ebp+0x10) %eax)
23969     (write-buffered *(ebp+0x10) "' must specify the type of its elements\n")
23970     (flush *(ebp+0x10))
23971     (stop *(ebp+0x14) 1)
23972     # never gets here
23973 
23974 $check-mu-index-stmt:error-base-address-array-type-on-stack:
23975     (write-buffered *(ebp+0x10) "fn ")
23976     8b/-> *(ebp+0xc) 0/r32/eax
23977     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23978     (write-buffered *(ebp+0x10) %eax)
23979     (write-buffered *(ebp+0x10) ": stmt index: var '")
23980     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
23981     (write-buffered *(ebp+0x10) %eax)
23982     (write-buffered *(ebp+0x10) "' is an addr to an array, and so must live in a register\n")
23983     (flush *(ebp+0x10))
23984     (stop *(ebp+0x14) 1)
23985     # never gets here
23986 
23987 $check-mu-index-stmt:error-base-array-type-in-register:
23988     (write-buffered *(ebp+0x10) "fn ")
23989     8b/-> *(ebp+0xc) 0/r32/eax
23990     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23991     (write-buffered *(ebp+0x10) %eax)
23992     (write-buffered *(ebp+0x10) ": stmt index: var '")
23993     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
23994     (write-buffered *(ebp+0x10) %eax)
23995     (write-buffered *(ebp+0x10) "' is an array, and so must live on the stack\n")
23996     (flush *(ebp+0x10))
23997     (stop *(ebp+0x14) 1)
23998     # never gets here
23999 
24000 $check-mu-index-stmt:error-too-few-inouts:
24001     (write-buffered *(ebp+0x10) "fn ")
24002     8b/-> *(ebp+0xc) 0/r32/eax
24003     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24004     (write-buffered *(ebp+0x10) %eax)
24005     (write-buffered *(ebp+0x10) ": stmt index: too few inouts (2 required)\n")
24006     (flush *(ebp+0x10))
24007     (stop *(ebp+0x14) 1)
24008     # never gets here
24009 
24010 $check-mu-index-stmt:error-invalid-index-type:
24011     (write-buffered *(ebp+0x10) "fn ")
24012     8b/-> *(ebp+0xc) 0/r32/eax
24013     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24014     (write-buffered *(ebp+0x10) %eax)
24015     (write-buffered *(ebp+0x10) ": stmt index: second argument '")
24016     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24017     (write-buffered *(ebp+0x10) %eax)
24018     (write-buffered *(ebp+0x10) "' must be an int or offset\n")
24019     (flush *(ebp+0x10))
24020     (stop *(ebp+0x14) 1)
24021     # never gets here
24022 
24023 $check-mu-index-stmt:error-index-offset-atom-type:
24024     (write-buffered *(ebp+0x10) "fn ")
24025     8b/-> *(ebp+0xc) 0/r32/eax
24026     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24027     (write-buffered *(ebp+0x10) %eax)
24028     (write-buffered *(ebp+0x10) ": stmt index: offset '")
24029     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24030     (write-buffered *(ebp+0x10) %eax)
24031     (write-buffered *(ebp+0x10) "' must specify the type of array elements\n")
24032     (flush *(ebp+0x10))
24033     (stop *(ebp+0x14) 1)
24034     # never gets here
24035 
24036 $check-mu-index-stmt:error-index-on-stack:
24037     (write-buffered *(ebp+0x10) "fn ")
24038     8b/-> *(ebp+0xc) 0/r32/eax
24039     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24040     (write-buffered *(ebp+0x10) %eax)
24041     (write-buffered *(ebp+0x10) ": stmt index: second argument '")
24042     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24043     (write-buffered *(ebp+0x10) %eax)
24044     (write-buffered *(ebp+0x10) "' must be in a register\n")
24045     (flush *(ebp+0x10))
24046     (stop *(ebp+0x14) 1)
24047     # never gets here
24048 
24049 $check-mu-index-stmt:error-index-needs-offset:
24050     (write-buffered *(ebp+0x10) "fn ")
24051     8b/-> *(ebp+0xc) 0/r32/eax
24052     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24053     (write-buffered *(ebp+0x10) %eax)
24054     (write-buffered *(ebp+0x10) ": stmt index: cannot take an int for array '")
24055     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
24056     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
24057     (lookup *eax *(eax+4))  # Var-name Var-name => eax
24058     (write-buffered *(ebp+0x10) %eax)
24059     (write-buffered *(ebp+0x10) "'; create an offset instead. See mu.md for details.\n")
24060     (flush *(ebp+0x10))
24061     (stop *(ebp+0x14) 1)
24062     # never gets here
24063 
24064 $check-mu-index-stmt:error-too-many-inouts:
24065     (write-buffered *(ebp+0x10) "fn ")
24066     8b/-> *(ebp+0xc) 0/r32/eax
24067     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24068     (write-buffered *(ebp+0x10) %eax)
24069     (write-buffered *(ebp+0x10) ": stmt index: too many inouts (2 required)\n")
24070     (flush *(ebp+0x10))
24071     (stop *(ebp+0x14) 1)
24072     # never gets here
24073 
24074 $check-mu-index-stmt:error-too-few-outputs:
24075     (write-buffered *(ebp+0x10) "fn ")
24076     8b/-> *(ebp+0xc) 0/r32/eax
24077     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24078     (write-buffered *(ebp+0x10) %eax)
24079     (write-buffered *(ebp+0x10) ": stmt index: must have an output\n")
24080     (flush *(ebp+0x10))
24081     (stop *(ebp+0x14) 1)
24082     # never gets here
24083 
24084 $check-mu-index-stmt:error-too-many-outputs:
24085     (write-buffered *(ebp+0x10) "fn ")
24086     8b/-> *(ebp+0xc) 0/r32/eax
24087     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24088     (write-buffered *(ebp+0x10) %eax)
24089     (write-buffered *(ebp+0x10) ": stmt index: too many outputs (1 required)\n")
24090     (flush *(ebp+0x10))
24091     (stop *(ebp+0x14) 1)
24092     # never gets here
24093 
24094 $check-mu-index-stmt:error-output-not-in-register:
24095     (write-buffered *(ebp+0x10) "fn ")
24096     8b/-> *(ebp+0xc) 0/r32/eax
24097     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24098     (write-buffered *(ebp+0x10) %eax)
24099     (write-buffered *(ebp+0x10) ": stmt index: output '")
24100     (lookup *edi *(edi+4))  # Var-name Var-name => eax
24101     (write-buffered *(ebp+0x10) %eax)
24102     (write-buffered *(ebp+0x10) "' is not in a register\n")
24103     (flush *(ebp+0x10))
24104     (stop *(ebp+0x14) 1)
24105     # never gets here
24106 
24107 $check-mu-index-stmt:error-output-type-not-address:
24108     (write-buffered *(ebp+0x10) "fn ")
24109     8b/-> *(ebp+0xc) 0/r32/eax
24110     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24111     (write-buffered *(ebp+0x10) %eax)
24112     (write-buffered *(ebp+0x10) ": stmt index: output '")
24113     (lookup *edi *(edi+4))  # Var-name Var-name => eax
24114     (write-buffered *(ebp+0x10) %eax)
24115     (write-buffered *(ebp+0x10) "' must be an addr\n")
24116     (flush *(ebp+0x10))
24117     (stop *(ebp+0x14) 1)
24118     # never gets here
24119 
24120 $check-mu-index-stmt:error-bad-output-type:
24121     (write-buffered *(ebp+0x10) "fn ")
24122     8b/-> *(ebp+0xc) 0/r32/eax
24123     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24124     (write-buffered *(ebp+0x10) %eax)
24125     (write-buffered *(ebp+0x10) ": stmt index: output '")
24126     (lookup *edi *(edi+4))  # Var-name Var-name => eax
24127     (write-buffered *(ebp+0x10) %eax)
24128     (write-buffered *(ebp+0x10) "' does not have the right type\n")
24129     (flush *(ebp+0x10))
24130     (stop *(ebp+0x14) 1)
24131     # never gets here
24132 
24133 check-mu-length-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
24134     # . prologue
24135     55/push-ebp
24136     89/<- %ebp 4/r32/esp
24137     # . save registers
24138     50/push-eax
24139     51/push-ecx
24140     52/push-edx
24141     53/push-ebx
24142     56/push-esi
24143     57/push-edi
24144     # esi = stmt
24145     8b/-> *(ebp+8) 6/r32/esi
24146     # - check for 0 inouts
24147     # var base/ecx: (addr var) = stmt->inouts->value
24148     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
24149 $check-mu-length-stmt:check-no-inouts:
24150     3d/compare-eax-and 0/imm32
24151     0f 84/jump-if-= $check-mu-length-stmt:error-too-few-inouts/disp32
24152     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
24153     89/<- %ecx 0/r32/eax
24154     # - check base type is either (addr array ...) in register or (array ...) on stack
24155     # var base-type/ebx: (addr type-tree) = lookup(base->type)
24156     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
24157     89/<- %ebx 0/r32/eax
24158     # if base-type is an atom, abort with a precise error
24159     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
24160     {
24161       74/jump-if-= break/disp8
24162       (is-simple-mu-type? %ebx 3)  # array => eax
24163       3d/compare-eax-and 0/imm32/false
24164       0f 85/jump-if-!= $check-mu-length-stmt:error-base-array-atom-type/disp32
24165       0f 84/jump-if-= $check-mu-length-stmt:error-base-non-array-type/disp32
24166     }
24167 $check-mu-length-stmt:base-is-compound:
24168     # if type->left not addr or array, abort
24169     {
24170       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24171       (is-simple-mu-type? %eax 2)  # addr => eax
24172       3d/compare-eax-and 0/imm32/false
24173       75/jump-if-!= break/disp8
24174       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24175       (is-simple-mu-type? %eax 3)  # array => eax
24176       3d/compare-eax-and 0/imm32/false
24177       75/jump-if-!= break/disp8
24178       e9/jump $check-mu-length-stmt:error-base-non-array-type/disp32
24179     }
24180     # if (type->left == addr) ensure type->right->left == array and type->register exists
24181     {
24182       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24183       (is-simple-mu-type? %eax 2)  # addr => eax
24184       3d/compare-eax-and 0/imm32/false
24185       74/jump-if-= break/disp8
24186 $check-mu-length-stmt:base-is-addr:
24187       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
24188       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
24189       (is-simple-mu-type? %eax 3)  # array => eax
24190       3d/compare-eax-and 0/imm32/false
24191       0f 84/jump-if-= $check-mu-length-stmt:error-base-non-array-type/disp32
24192 $check-mu-length-stmt:check-base-addr-is-register:
24193       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
24194       0f 84/jump-if-= $check-mu-length-stmt:error-base-address-array-type-on-stack/disp32
24195     }
24196     # if (type->left == array) ensure type->register doesn't exist
24197     {
24198       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24199       (is-simple-mu-type? %eax 3)  # array => eax
24200       3d/compare-eax-and 0/imm32/false
24201       74/jump-if-= break/disp8
24202 $check-mu-length-stmt:base-is-array:
24203       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
24204       0f 85/jump-if-!= $check-mu-length-stmt:error-base-array-type-in-register/disp32
24205     }
24206     # if (base-type->left == addr) base-type = base-type->right
24207     {
24208       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24209       (is-simple-mu-type? %eax 2)  # addr => eax
24210       3d/compare-eax-and 0/imm32/false
24211       74/jump-if-= break/disp8
24212       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
24213       89/<- %ebx 0/r32/eax
24214     }
24215     # - check for too many inouts
24216     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
24217     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
24218     3d/compare-eax-and 0/imm32/false
24219     0f 85/jump-if-!= $check-mu-length-stmt:error-too-many-inouts/disp32
24220     # - check for 0 outputs
24221     # var output/edi: (addr var) = stmt->outputs->value
24222     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
24223     3d/compare-eax-and 0/imm32/false
24224     0f 84/jump-if-= $check-mu-length-stmt:error-too-few-outputs/disp32
24225     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
24226     89/<- %edi 0/r32/eax
24227     # - check output type
24228     # must have a non-atomic type
24229     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
24230     (is-simple-mu-type? %eax 1)  # int => eax
24231     3d/compare-eax-and 0/imm32/false
24232     0f 84/jump-if-= $check-mu-length-stmt:error-invalid-output-type/disp32
24233     # - check for too many outputs
24234     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
24235     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
24236     3d/compare-eax-and 0/imm32/false
24237     0f 85/jump-if-!= $check-mu-length-stmt:error-too-many-outputs/disp32
24238 $check-mu-length-stmt:end:
24239     # . restore registers
24240     5f/pop-to-edi
24241     5e/pop-to-esi
24242     5b/pop-to-ebx
24243     5a/pop-to-edx
24244     59/pop-to-ecx
24245     58/pop-to-eax
24246     # . epilogue
24247     89/<- %esp 5/r32/ebp
24248     5d/pop-to-ebp
24249     c3/return
24250 
24251 $check-mu-length-stmt:error-base-non-array-type:
24252     (write-buffered *(ebp+0x10) "fn ")
24253     8b/-> *(ebp+0xc) 0/r32/eax
24254     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24255     (write-buffered *(ebp+0x10) %eax)
24256     (write-buffered *(ebp+0x10) ": stmt length: var '")
24257     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24258     (write-buffered *(ebp+0x10) %eax)
24259     (write-buffered *(ebp+0x10) "' is not an array\n")
24260     (flush *(ebp+0x10))
24261     (stop *(ebp+0x14) 1)
24262     # never gets here
24263 
24264 $check-mu-length-stmt:error-base-array-atom-type:
24265     (write-buffered *(ebp+0x10) "fn ")
24266     8b/-> *(ebp+0xc) 0/r32/eax
24267     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24268     (write-buffered *(ebp+0x10) %eax)
24269     (write-buffered *(ebp+0x10) ": stmt length: array '")
24270     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24271     (write-buffered *(ebp+0x10) %eax)
24272     (write-buffered *(ebp+0x10) "' must specify the type of its elements\n")
24273     (flush *(ebp+0x10))
24274     (stop *(ebp+0x14) 1)
24275     # never gets here
24276 
24277 $check-mu-length-stmt:error-base-address-array-type-on-stack:
24278     (write-buffered *(ebp+0x10) "fn ")
24279     8b/-> *(ebp+0xc) 0/r32/eax
24280     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24281     (write-buffered *(ebp+0x10) %eax)
24282     (write-buffered *(ebp+0x10) ": stmt length: var '")
24283     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24284     (write-buffered *(ebp+0x10) %eax)
24285     (write-buffered *(ebp+0x10) "' is an addr to an array, and so must live in a register\n")
24286     (flush *(ebp+0x10))
24287     (stop *(ebp+0x14) 1)
24288     # never gets here
24289 
24290 $check-mu-length-stmt:error-base-array-type-in-register:
24291     (write-buffered *(ebp+0x10) "fn ")
24292     8b/-> *(ebp+0xc) 0/r32/eax
24293     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24294     (write-buffered *(ebp+0x10) %eax)
24295     (write-buffered *(ebp+0x10) ": stmt length: var '")
24296     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24297     (write-buffered *(ebp+0x10) %eax)
24298     (write-buffered *(ebp+0x10) "' is an array, and so must live on the stack\n")
24299     (flush *(ebp+0x10))
24300     (stop *(ebp+0x14) 1)
24301     # never gets here
24302 
24303 $check-mu-length-stmt:error-too-few-inouts:
24304     (write-buffered *(ebp+0x10) "fn ")
24305     8b/-> *(ebp+0xc) 0/r32/eax
24306     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24307     (write-buffered *(ebp+0x10) %eax)
24308     (write-buffered *(ebp+0x10) ": stmt length: too few inouts (1 required)\n")
24309     (flush *(ebp+0x10))
24310     (stop *(ebp+0x14) 1)
24311     # never gets here
24312 
24313 $check-mu-length-stmt:error-invalid-index-type:
24314     (write-buffered *(ebp+0x10) "fn ")
24315     8b/-> *(ebp+0xc) 0/r32/eax
24316     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24317     (write-buffered *(ebp+0x10) %eax)
24318     (write-buffered *(ebp+0x10) ": stmt length: second argument '")
24319     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24320     (write-buffered *(ebp+0x10) %eax)
24321     (write-buffered *(ebp+0x10) "' must be an int or offset\n")
24322     (flush *(ebp+0x10))
24323     (stop *(ebp+0x14) 1)
24324     # never gets here
24325 
24326 $check-mu-length-stmt:error-index-offset-atom-type:
24327     (write-buffered *(ebp+0x10) "fn ")
24328     8b/-> *(ebp+0xc) 0/r32/eax
24329     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24330     (write-buffered *(ebp+0x10) %eax)
24331     (write-buffered *(ebp+0x10) ": stmt length: offset '")
24332     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24333     (write-buffered *(ebp+0x10) %eax)
24334     (write-buffered *(ebp+0x10) "' must specify the type of array elements\n")
24335     (flush *(ebp+0x10))
24336     (stop *(ebp+0x14) 1)
24337     # never gets here
24338 
24339 $check-mu-length-stmt:error-index-on-stack:
24340     (write-buffered *(ebp+0x10) "fn ")
24341     8b/-> *(ebp+0xc) 0/r32/eax
24342     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24343     (write-buffered *(ebp+0x10) %eax)
24344     (write-buffered *(ebp+0x10) ": stmt length: second argument '")
24345     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24346     (write-buffered *(ebp+0x10) %eax)
24347     (write-buffered *(ebp+0x10) "' must be in a register\n")
24348     (flush *(ebp+0x10))
24349     (stop *(ebp+0x14) 1)
24350     # never gets here
24351 
24352 $check-mu-length-stmt:error-index-needs-offset:
24353     (write-buffered *(ebp+0x10) "fn ")
24354     8b/-> *(ebp+0xc) 0/r32/eax
24355     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24356     (write-buffered *(ebp+0x10) %eax)
24357     (write-buffered *(ebp+0x10) ": stmt length: cannot take an int for array '")
24358     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
24359     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
24360     (lookup *eax *(eax+4))  # Var-name Var-name => eax
24361     (write-buffered *(ebp+0x10) %eax)
24362     (write-buffered *(ebp+0x10) "'; create an offset instead. See mu.md for details.\n")
24363     (flush *(ebp+0x10))
24364     (stop *(ebp+0x14) 1)
24365     # never gets here
24366 
24367 $check-mu-length-stmt:error-too-many-inouts:
24368     (write-buffered *(ebp+0x10) "fn ")
24369     8b/-> *(ebp+0xc) 0/r32/eax
24370     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24371     (write-buffered *(ebp+0x10) %eax)
24372     (write-buffered *(ebp+0x10) ": stmt length: too many inouts (1 required)\n")
24373     (flush *(ebp+0x10))
24374     (stop *(ebp+0x14) 1)
24375     # never gets here
24376 
24377 $check-mu-length-stmt:error-too-few-outputs:
24378     (write-buffered *(ebp+0x10) "fn ")
24379     8b/-> *(ebp+0xc) 0/r32/eax
24380     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24381     (write-buffered *(ebp+0x10) %eax)
24382     (write-buffered *(ebp+0x10) ": stmt length: must have an output\n")
24383     (flush *(ebp+0x10))
24384     (stop *(ebp+0x14) 1)
24385     # never gets here
24386 
24387 $check-mu-length-stmt:error-too-many-outputs:
24388     (write-buffered *(ebp+0x10) "fn ")
24389     8b/-> *(ebp+0xc) 0/r32/eax
24390     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24391     (write-buffered *(ebp+0x10) %eax)
24392     (write-buffered *(ebp+0x10) ": stmt length: too many outputs (1 required)\n")
24393     (flush *(ebp+0x10))
24394     (stop *(ebp+0x14) 1)
24395     # never gets here
24396 
24397 $check-mu-length-stmt:error-output-not-in-register:
24398     (write-buffered *(ebp+0x10) "fn ")
24399     8b/-> *(ebp+0xc) 0/r32/eax
24400     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24401     (write-buffered *(ebp+0x10) %eax)
24402     (write-buffered *(ebp+0x10) ": stmt length: output '")
24403     (lookup *edi *(edi+4))  # Var-name Var-name => eax
24404     (write-buffered *(ebp+0x10) %eax)
24405     (write-buffered *(ebp+0x10) "' is not in a register\n")
24406     (flush *(ebp+0x10))
24407     (stop *(ebp+0x14) 1)
24408     # never gets here
24409 
24410 $check-mu-length-stmt:error-invalid-output-type:
24411     (write-buffered *(ebp+0x10) "fn ")
24412     8b/-> *(ebp+0xc) 0/r32/eax
24413     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24414     (write-buffered *(ebp+0x10) %eax)
24415     (write-buffered *(ebp+0x10) ": stmt length: output '")
24416     (lookup *edi *(edi+4))  # Var-name Var-name => eax
24417     (write-buffered *(ebp+0x10) %eax)
24418     (write-buffered *(ebp+0x10) "' does not have the right type\n")
24419     (flush *(ebp+0x10))
24420     (stop *(ebp+0x14) 1)
24421     # never gets here
24422 
24423 check-mu-compute-offset-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
24424     # . prologue
24425     55/push-ebp
24426     89/<- %ebp 4/r32/esp
24427     # . save registers
24428     50/push-eax
24429     51/push-ecx
24430     52/push-edx
24431     53/push-ebx
24432     56/push-esi
24433     57/push-edi
24434     # esi = stmt
24435     8b/-> *(ebp+8) 6/r32/esi
24436     # - check for 0 inouts
24437     # var base/ecx: (addr var) = stmt->inouts->value
24438     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
24439 $check-mu-compute-offset-stmt:check-no-inouts:
24440     3d/compare-eax-and 0/imm32
24441     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-too-few-inouts/disp32
24442     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
24443     89/<- %ecx 0/r32/eax
24444     # - check base type is either (addr array ...) in register or (array ...) on stack
24445     # var base-type/ebx: (addr type-tree) = lookup(base->type)
24446     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
24447     89/<- %ebx 0/r32/eax
24448     # if base-type is an atom, abort with a precise error
24449     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
24450     {
24451       74/jump-if-= break/disp8
24452       (is-simple-mu-type? %ebx 3)  # array => eax
24453       3d/compare-eax-and 0/imm32/false
24454       0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-base-array-atom-type/disp32
24455       0f 84/jump-if-= $check-mu-compute-offset-stmt:error-base-non-array-type/disp32
24456     }
24457 $check-mu-compute-offset-stmt:base-is-compound:
24458     # if type->left not addr or array, abort
24459     {
24460       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24461       (is-simple-mu-type? %eax 2)  # addr => eax
24462       3d/compare-eax-and 0/imm32/false
24463       75/jump-if-!= break/disp8
24464       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24465       (is-simple-mu-type? %eax 3)  # array => eax
24466       3d/compare-eax-and 0/imm32/false
24467       75/jump-if-!= break/disp8
24468       e9/jump $check-mu-compute-offset-stmt:error-base-non-array-type/disp32
24469     }
24470     # if (type->left == addr) ensure type->right->left == array and type->register exists
24471     {
24472       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24473       (is-simple-mu-type? %eax 2)  # addr => eax
24474       3d/compare-eax-and 0/imm32/false
24475       74/jump-if-= break/disp8
24476 $check-mu-compute-offset-stmt:base-is-addr:
24477       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
24478       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
24479       (is-simple-mu-type? %eax 3)  # array => eax
24480       3d/compare-eax-and 0/imm32/false
24481       0f 84/jump-if-= $check-mu-compute-offset-stmt:error-base-non-array-type/disp32
24482     }
24483     # if (base-type->left == addr) base-type = base-type->right
24484     {
24485       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24486       (is-simple-mu-type? %eax 2)  # addr => eax
24487       3d/compare-eax-and 0/imm32/false
24488       74/jump-if-= break/disp8
24489       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
24490       89/<- %ebx 0/r32/eax
24491     }
24492     # - check for 1 inout
24493     # var index/ecx: (addr stmt-var) = stmt->inouts->next->value
24494     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
24495     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
24496 $check-mu-compute-offset-stmt:check-single-inout:
24497     3d/compare-eax-and 0/imm32
24498     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-too-few-inouts/disp32
24499     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
24500     89/<- %ecx 0/r32/eax
24501     # - check index is either a literal or register
24502     # var index-type/edx: (addr type-tree)
24503     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
24504     89/<- %edx 0/r32/eax
24505     # index type must be a literal or int
24506     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
24507     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-invalid-index-type/disp32
24508     {
24509 $check-mu-compute-offset-stmt:index-type-is-atom:
24510       (is-simple-mu-type? %edx 0)  # literal => eax
24511       3d/compare-eax-and 0/imm32/false
24512       75/jump-if-!= break/disp8
24513       (is-simple-mu-type? %edx 1)  # int => eax
24514       3d/compare-eax-and 0/imm32/false
24515       75/jump-if-!= break/disp8
24516       e9/jump $check-mu-compute-offset-stmt:error-invalid-index-type/disp32
24517     }
24518     # - check for too many inouts
24519     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
24520     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
24521     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
24522     3d/compare-eax-and 0/imm32/false
24523     0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-too-many-inouts/disp32
24524     # - check for 0 outputs
24525     # var output/edi: (addr var) = stmt->outputs->value
24526     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
24527     3d/compare-eax-and 0/imm32/false
24528     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-too-few-outputs/disp32
24529     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
24530     89/<- %edi 0/r32/eax
24531     # - check output type
24532     # must have a non-atomic type
24533     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
24534     89/<- %edx 0/r32/eax
24535     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
24536     0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-output-type-not-offset/disp32
24537     # type must start with (offset ...)
24538     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
24539     (is-simple-mu-type? %eax 7)  # offset => eax
24540     3d/compare-eax-and 0/imm32/false
24541     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-output-type-not-offset/disp32
24542     # if tail(base-type) != tail(output-type) abort
24543     (type-tail %ebx)  # => eax
24544     89/<- %ebx 0/r32/eax
24545     (type-tail %edx)  # => eax
24546     (type-equal? %ebx %eax)  # => eax
24547     3d/compare-eax-and 0/imm32/false
24548     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-bad-output-type/disp32
24549     # - check for too many outputs
24550     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
24551     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
24552     3d/compare-eax-and 0/imm32/false
24553     0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-too-many-outputs/disp32
24554 $check-mu-compute-offset-stmt:end:
24555     # . restore registers
24556     5f/pop-to-edi
24557     5e/pop-to-esi
24558     5b/pop-to-ebx
24559     5a/pop-to-edx
24560     59/pop-to-ecx
24561     58/pop-to-eax
24562     # . epilogue
24563     89/<- %esp 5/r32/ebp
24564     5d/pop-to-ebp
24565     c3/return
24566 
24567 $check-mu-compute-offset-stmt:error-base-non-array-type:
24568     (write-buffered *(ebp+0x10) "fn ")
24569     8b/-> *(ebp+0xc) 0/r32/eax
24570     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24571     (write-buffered *(ebp+0x10) %eax)
24572     (write-buffered *(ebp+0x10) ": stmt compute-offset: var '")
24573     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24574     (write-buffered *(ebp+0x10) %eax)
24575     (write-buffered *(ebp+0x10) "' is not an array\n")
24576     (flush *(ebp+0x10))
24577     (stop *(ebp+0x14) 1)
24578     # never gets here
24579 
24580 $check-mu-compute-offset-stmt:error-base-array-atom-type:
24581     (write-buffered *(ebp+0x10) "fn ")
24582     8b/-> *(ebp+0xc) 0/r32/eax
24583     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24584     (write-buffered *(ebp+0x10) %eax)
24585     (write-buffered *(ebp+0x10) ": stmt compute-offset: array '")
24586     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24587     (write-buffered *(ebp+0x10) %eax)
24588     (write-buffered *(ebp+0x10) "' must specify the type of its elements\n")
24589     (flush *(ebp+0x10))
24590     (stop *(ebp+0x14) 1)
24591     # never gets here
24592 
24593 $check-mu-compute-offset-stmt:error-too-few-inouts:
24594     (write-buffered *(ebp+0x10) "fn ")
24595     8b/-> *(ebp+0xc) 0/r32/eax
24596     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24597     (write-buffered *(ebp+0x10) %eax)
24598     (write-buffered *(ebp+0x10) ": stmt compute-offset: too few inouts (2 required)\n")
24599     (flush *(ebp+0x10))
24600     (stop *(ebp+0x14) 1)
24601     # never gets here
24602 
24603 $check-mu-compute-offset-stmt:error-invalid-index-type:
24604     (write-buffered *(ebp+0x10) "fn ")
24605     8b/-> *(ebp+0xc) 0/r32/eax
24606     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24607     (write-buffered *(ebp+0x10) %eax)
24608     (write-buffered *(ebp+0x10) ": stmt compute-offset: second argument '")
24609     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24610     (write-buffered *(ebp+0x10) %eax)
24611     (write-buffered *(ebp+0x10) "' must be an int\n")
24612     (flush *(ebp+0x10))
24613     (stop *(ebp+0x14) 1)
24614     # never gets here
24615 
24616 $check-mu-compute-offset-stmt:error-index-offset-atom-type:
24617     (write-buffered *(ebp+0x10) "fn ")
24618     8b/-> *(ebp+0xc) 0/r32/eax
24619     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24620     (write-buffered *(ebp+0x10) %eax)
24621     (write-buffered *(ebp+0x10) ": stmt compute-offset: offset '")
24622     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24623     (write-buffered *(ebp+0x10) %eax)
24624     (write-buffered *(ebp+0x10) "' must specify the type of array elements\n")
24625     (flush *(ebp+0x10))
24626     (stop *(ebp+0x14) 1)
24627     # never gets here
24628 
24629 $check-mu-compute-offset-stmt:error-index-on-stack:
24630     (write-buffered *(ebp+0x10) "fn ")
24631     8b/-> *(ebp+0xc) 0/r32/eax
24632     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24633     (write-buffered *(ebp+0x10) %eax)
24634     (write-buffered *(ebp+0x10) ": stmt compute-offset: second argument '")
24635     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24636     (write-buffered *(ebp+0x10) %eax)
24637     (write-buffered *(ebp+0x10) "' must be in a register\n")
24638     (flush *(ebp+0x10))
24639     (stop *(ebp+0x14) 1)
24640     # never gets here
24641 
24642 $check-mu-compute-offset-stmt:error-too-many-inouts:
24643     (write-buffered *(ebp+0x10) "fn ")
24644     8b/-> *(ebp+0xc) 0/r32/eax
24645     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24646     (write-buffered *(ebp+0x10) %eax)
24647     (write-buffered *(ebp+0x10) ": stmt compute-offset: too many inouts (2 required)\n")
24648     (flush *(ebp+0x10))
24649     (stop *(ebp+0x14) 1)
24650     # never gets here
24651 
24652 $check-mu-compute-offset-stmt:error-too-few-outputs:
24653     (write-buffered *(ebp+0x10) "fn ")
24654     8b/-> *(ebp+0xc) 0/r32/eax
24655     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24656     (write-buffered *(ebp+0x10) %eax)
24657     (write-buffered *(ebp+0x10) ": stmt compute-offset: must have an output\n")
24658     (flush *(ebp+0x10))
24659     (stop *(ebp+0x14) 1)
24660     # never gets here
24661 
24662 $check-mu-compute-offset-stmt:error-too-many-outputs:
24663     (write-buffered *(ebp+0x10) "fn ")
24664     8b/-> *(ebp+0xc) 0/r32/eax
24665     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24666     (write-buffered *(ebp+0x10) %eax)
24667     (write-buffered *(ebp+0x10) ": stmt compute-offset: too many outputs (1 required)\n")
24668     (flush *(ebp+0x10))
24669     (stop *(ebp+0x14) 1)
24670     # never gets here
24671 
24672 $check-mu-compute-offset-stmt:error-output-not-in-register:
24673     (write-buffered *(ebp+0x10) "fn ")
24674     8b/-> *(ebp+0xc) 0/r32/eax
24675     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24676     (write-buffered *(ebp+0x10) %eax)
24677     (write-buffered *(ebp+0x10) ": stmt compute-offset: output '")
24678     (lookup *edi *(edi+4))  # Var-name Var-name => eax
24679     (write-buffered *(ebp+0x10) %eax)
24680     (write-buffered *(ebp+0x10) "' is not in a register\n")
24681     (flush *(ebp+0x10))
24682     (stop *(ebp+0x14) 1)
24683     # never gets here
24684 
24685 $check-mu-compute-offset-stmt:error-output-type-not-offset:
24686     (write-buffered *(ebp+0x10) "fn ")
24687     8b/-> *(ebp+0xc) 0/r32/eax
24688     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24689     (write-buffered *(ebp+0x10) %eax)
24690     (write-buffered *(ebp+0x10) ": stmt compute-offset: output '")
24691     (lookup *edi *(edi+4))  # Var-name Var-name => eax
24692     (write-buffered *(ebp+0x10) %eax)
24693     (write-buffered *(ebp+0x10) "' must be an offset\n")
24694     (flush *(ebp+0x10))
24695     (stop *(ebp+0x14) 1)
24696     # never gets here
24697 
24698 $check-mu-compute-offset-stmt:error-bad-output-type:
24699     (write-buffered *(ebp+0x10) "fn ")
24700     8b/-> *(ebp+0xc) 0/r32/eax
24701     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24702     (write-buffered *(ebp+0x10) %eax)
24703     (write-buffered *(ebp+0x10) ": stmt compute-offset: output '")
24704     (lookup *edi *(edi+4))  # Var-name Var-name => eax
24705     (write-buffered *(ebp+0x10) %eax)
24706     (write-buffered *(ebp+0x10) "' does not have the right type\n")
24707     (flush *(ebp+0x10))
24708     (stop *(ebp+0x14) 1)
24709     # never gets here
24710 
24711 check-mu-copy-object-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
24712     # . prologue
24713     55/push-ebp
24714     89/<- %ebp 4/r32/esp
24715     # . save registers
24716     50/push-eax
24717     51/push-ecx
24718     53/push-ebx
24719     56/push-esi
24720     57/push-edi
24721     # esi = stmt
24722     8b/-> *(ebp+8) 6/r32/esi
24723 $check-mu-copy-object-stmt:check-for-output:
24724     # if stmt->outputs abort
24725     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
24726     3d/compare-eax-and 0/imm32
24727     0f 85/jump-if-!= $check-mu-copy-object-stmt:error-too-many-outputs/disp32
24728 $check-mu-copy-object-stmt:get-left:
24729     # var dest/edi: (addr stmt-var) = stmt->inouts
24730     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
24731     89/<- %edi 0/r32/eax
24732     # zero inouts
24733     3d/compare-eax-and 0/imm32
24734     0f 84/jump-if-= $check-mu-copy-object-stmt:error-incorrect-inouts/disp32
24735 $check-mu-copy-object-stmt:get-src:
24736     # var src/esi: (addr stmt-var) = dest->next
24737     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
24738     89/<- %esi 0/r32/eax
24739     # 1 inout
24740     3d/compare-eax-and 0/imm32
24741     0f 84/jump-if-= $check-mu-copy-object-stmt:error-incorrect-inouts/disp32
24742     # > 2 inouts
24743     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
24744     3d/compare-eax-and 0/imm32
24745     0f 85/jump-if-!= $check-mu-copy-object-stmt:error-incorrect-inouts/disp32
24746 $check-mu-copy-object-stmt:types:
24747     # var src-type/ecx: (addr type-tree) = src->value->type
24748     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
24749     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
24750     89/<- %ecx 0/r32/eax
24751     # if (src->is-deref?) src-type = src-type->payload
24752     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
24753     3d/compare-eax-and 0/imm32/false
24754     {
24755       74/jump-if-= break/disp8
24756       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
24757       # if src-type->right is null, src-type = src-type->left
24758       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
24759       {
24760         75/jump-if-!= break/disp8
24761         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
24762       }
24763       89/<- %ecx 0/r32/eax
24764     }
24765     # if src-type is not addr, abort
24766     (is-mu-addr-type? %ecx)  # => eax
24767     3d/compare-eax-and 0/imm32/false
24768     0f 84/jump-if-= $check-mu-copy-object-stmt:error-invalid-types/disp32
24769     # var dest-type/ebx: (addr type-tree) = dest->value->type
24770     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
24771     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
24772     89/<- %ebx 0/r32/eax
24773     # if (dest->is-deref?) dest-type = dest-type->payload
24774     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
24775     3d/compare-eax-and 0/imm32/false
24776     {
24777       74/jump-if-= break/disp8
24778       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
24779       # if dest-type->right is null, dest-type = dest-type->left
24780       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
24781       {
24782         75/jump-if-!= break/disp8
24783         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
24784       }
24785       89/<- %ebx 0/r32/eax
24786     }
24787     # if (dest-type != src-type) abort
24788     (type-equal? %ecx %ebx)  # => eax
24789     3d/compare-eax-and 0/imm32
24790     0f 84/jump-if-= $check-mu-copy-object-stmt:error-invalid-types/disp32
24791 $check-mu-copy-object-stmt:end:
24792     # . restore registers
24793     5f/pop-to-edi
24794     5e/pop-to-esi
24795     5b/pop-to-ebx
24796     59/pop-to-ecx
24797     58/pop-to-eax
24798     # . epilogue
24799     89/<- %esp 5/r32/ebp
24800     5d/pop-to-ebp
24801     c3/return
24802 
24803 $check-mu-copy-object-stmt:error-incorrect-inouts:
24804     (write-buffered *(ebp+0x10) "fn ")
24805     8b/-> *(ebp+0xc) 0/r32/eax
24806     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24807     (write-buffered *(ebp+0x10) %eax)
24808     (write-buffered *(ebp+0x10) ": stmt 'copy-object' must have two inouts\n")
24809     (flush *(ebp+0x10))
24810     (stop *(ebp+0x14) 1)
24811     # never gets here
24812 
24813 $check-mu-copy-object-stmt:error-too-many-outputs:
24814     (write-buffered *(ebp+0x10) "fn ")
24815     8b/-> *(ebp+0xc) 0/r32/eax
24816     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24817     (write-buffered *(ebp+0x10) %eax)
24818     (write-buffered *(ebp+0x10) ": stmt 'copy-object' must not have any outputs\n")
24819     (flush *(ebp+0x10))
24820     (stop *(ebp+0x14) 1)
24821     # never gets here
24822 
24823 $check-mu-copy-object-stmt:error-invalid-types:
24824     (write-buffered *(ebp+0x10) "fn ")
24825     8b/-> *(ebp+0xc) 0/r32/eax
24826     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24827     (write-buffered *(ebp+0x10) %eax)
24828     (write-buffered *(ebp+0x10) ": stmt copy-object: two inouts with identical addr types expected\n")
24829     (flush *(ebp+0x10))
24830     (stop *(ebp+0x14) 1)
24831     # never gets here
24832 
24833 check-mu-clear-object-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
24834     # . prologue
24835     55/push-ebp
24836     89/<- %ebp 4/r32/esp
24837     # . save registers
24838     50/push-eax
24839     51/push-ecx
24840     53/push-ebx
24841     56/push-esi
24842     57/push-edi
24843     # esi = stmt
24844     8b/-> *(ebp+8) 6/r32/esi
24845 $check-mu-clear-object-stmt:check-for-output:
24846     # if stmt->outputs abort
24847     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
24848     3d/compare-eax-and 0/imm32
24849     0f 85/jump-if-!= $check-mu-clear-object-stmt:error-too-many-outputs/disp32
24850 $check-mu-clear-object-stmt:get-left:
24851     # var dest/edi: (addr stmt-var) = stmt->inouts
24852     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
24853     89/<- %edi 0/r32/eax
24854     # zero inouts
24855     3d/compare-eax-and 0/imm32
24856     0f 84/jump-if-= $check-mu-clear-object-stmt:error-incorrect-inouts/disp32
24857 $check-mu-clear-object-stmt:get-src:
24858     # > 1 inout
24859     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
24860     3d/compare-eax-and 0/imm32
24861     0f 85/jump-if-!= $check-mu-clear-object-stmt:error-incorrect-inouts/disp32
24862 $check-mu-clear-object-stmt:types:
24863     # var src-type/ecx: (addr type-tree) = src->value->type
24864     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
24865     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
24866     89/<- %ecx 0/r32/eax
24867     # if (src->is-deref?) src-type = src-type->payload
24868     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
24869     3d/compare-eax-and 0/imm32/false
24870     {
24871       74/jump-if-= break/disp8
24872       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
24873       # if src-type->right is null, src-type = src-type->left
24874       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
24875       {
24876         75/jump-if-!= break/disp8
24877         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
24878       }
24879       89/<- %ecx 0/r32/eax
24880     }
24881     # if src-type is not addr, abort
24882     (is-mu-addr-type? %ecx)  # => eax
24883     3d/compare-eax-and 0/imm32/false
24884     0f 84/jump-if-= $check-mu-clear-object-stmt:error-invalid-type/disp32
24885 $check-mu-clear-object-stmt:end:
24886     # . restore registers
24887     5f/pop-to-edi
24888     5e/pop-to-esi
24889     5b/pop-to-ebx
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 $check-mu-clear-object-stmt:error-incorrect-inouts:
24898     (write-buffered *(ebp+0x10) "fn ")
24899     8b/-> *(ebp+0xc) 0/r32/eax
24900     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24901     (write-buffered *(ebp+0x10) %eax)
24902     (write-buffered *(ebp+0x10) ": stmt 'clear-object' must have a single inout\n")
24903     (flush *(ebp+0x10))
24904     (stop *(ebp+0x14) 1)
24905     # never gets here
24906 
24907 $check-mu-clear-object-stmt:error-too-many-outputs:
24908     (write-buffered *(ebp+0x10) "fn ")
24909     8b/-> *(ebp+0xc) 0/r32/eax
24910     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24911     (write-buffered *(ebp+0x10) %eax)
24912     (write-buffered *(ebp+0x10) ": stmt 'clear-object' must not have any outputs\n")
24913     (flush *(ebp+0x10))
24914     (stop *(ebp+0x14) 1)
24915     # never gets here
24916 
24917 $check-mu-clear-object-stmt:error-invalid-type:
24918     (write-buffered *(ebp+0x10) "fn ")
24919     8b/-> *(ebp+0xc) 0/r32/eax
24920     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24921     (write-buffered *(ebp+0x10) %eax)
24922     (write-buffered *(ebp+0x10) ": stmt clear-object: inout must have an addr type\n")
24923     (flush *(ebp+0x10))
24924     (stop *(ebp+0x14) 1)
24925     # never gets here
24926 
24927 check-mu-allocate-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
24928     # . prologue
24929     55/push-ebp
24930     89/<- %ebp 4/r32/esp
24931     # . save registers
24932     50/push-eax
24933     53/push-ebx
24934     56/push-esi
24935     57/push-edi
24936     # esi = stmt
24937     8b/-> *(ebp+8) 6/r32/esi
24938 $check-mu-allocate-stmt:check-for-output:
24939     # if stmt->outputs abort
24940     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
24941     3d/compare-eax-and 0/imm32
24942     0f 85/jump-if-!= $check-mu-allocate-stmt:error-too-many-outputs/disp32
24943 $check-mu-allocate-stmt:get-target:
24944     # var target/edi: (addr stmt-var) = stmt->inouts
24945     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
24946     89/<- %edi 0/r32/eax
24947     # zero inouts
24948     3d/compare-eax-and 0/imm32
24949     0f 84/jump-if-= $check-mu-allocate-stmt:error-incorrect-inouts/disp32
24950     # > 1 inouts
24951     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
24952     3d/compare-eax-and 0/imm32
24953     0f 85/jump-if-!= $check-mu-allocate-stmt:error-incorrect-inouts/disp32
24954 $check-mu-allocate-stmt:check-type:
24955     # var target-type/ebx: (addr type-tree) = target->value->type
24956     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
24957     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
24958     89/<- %ebx 0/r32/eax
24959     # if (target->is-deref?) target-type = target-type->payload
24960     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
24961     3d/compare-eax-and 0/imm32/false
24962     {
24963       74/jump-if-= break/disp8
24964       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
24965       # if target-type->right is null, target-type = target-type->left
24966       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
24967       {
24968         75/jump-if-!= break/disp8
24969         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
24970       }
24971       89/<- %ebx 0/r32/eax
24972     }
24973     # if target-type is not addr, abort
24974     (is-mu-addr-type? %ebx)  # => eax
24975     3d/compare-eax-and 0/imm32/false
24976     0f 84/jump-if-= $check-mu-allocate-stmt:error-invalid-type/disp32
24977     # if target-type->right is an atom, abort
24978     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
24979     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
24980     0f 85/jump-if-!= $check-mu-allocate-stmt:error-invalid-type/disp32
24981     # if target-type->right->left is not handle, abort
24982     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
24983     (is-simple-mu-type? %eax 4)  # handle => eax
24984     3d/compare-eax-and 0/imm32/false
24985     0f 84/jump-if-= $check-mu-allocate-stmt:error-invalid-type/disp32
24986 $check-mu-allocate-stmt:end:
24987     # . restore registers
24988     5f/pop-to-edi
24989     5e/pop-to-esi
24990     5b/pop-to-ebx
24991     58/pop-to-eax
24992     # . epilogue
24993     89/<- %esp 5/r32/ebp
24994     5d/pop-to-ebp
24995     c3/return
24996 
24997 $check-mu-allocate-stmt:error-incorrect-inouts:
24998     (write-buffered *(ebp+0x10) "fn ")
24999     8b/-> *(ebp+0xc) 0/r32/eax
25000     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25001     (write-buffered *(ebp+0x10) %eax)
25002     (write-buffered *(ebp+0x10) ": stmt 'allocate' must have a single inout\n")
25003     (flush *(ebp+0x10))
25004     (stop *(ebp+0x14) 1)
25005     # never gets here
25006 
25007 $check-mu-allocate-stmt:error-too-many-outputs:
25008     (write-buffered *(ebp+0x10) "fn ")
25009     8b/-> *(ebp+0xc) 0/r32/eax
25010     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25011     (write-buffered *(ebp+0x10) %eax)
25012     (write-buffered *(ebp+0x10) ": stmt 'allocate' must not have any outputs\n")
25013     (flush *(ebp+0x10))
25014     (stop *(ebp+0x14) 1)
25015     # never gets here
25016 
25017 $check-mu-allocate-stmt:error-invalid-type:
25018     (write-buffered *(ebp+0x10) "fn ")
25019     8b/-> *(ebp+0xc) 0/r32/eax
25020     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25021     (write-buffered *(ebp+0x10) %eax)
25022     (write-buffered *(ebp+0x10) ": stmt allocate: inout '")
25023     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
25024     (lookup *eax *(eax+4))  # Var-name Var-name => eax
25025     (write-buffered *(ebp+0x10) %eax)
25026     (write-buffered *(ebp+0x10) "' must have type (addr handle ...)\n")
25027     (flush *(ebp+0x10))
25028     (stop *(ebp+0x14) 1)
25029     # never gets here
25030 
25031 check-mu-populate-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
25032     # . prologue
25033     55/push-ebp
25034     89/<- %ebp 4/r32/esp
25035     # . save registers
25036     50/push-eax
25037     53/push-ebx
25038     56/push-esi
25039     57/push-edi
25040     # esi = stmt
25041     8b/-> *(ebp+8) 6/r32/esi
25042 $check-mu-populate-stmt:check-for-output:
25043     # if stmt->outputs abort
25044     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
25045     3d/compare-eax-and 0/imm32
25046     0f 85/jump-if-!= $check-mu-populate-stmt:error-too-many-outputs/disp32
25047 $check-mu-populate-stmt:get-target:
25048     # var target/edi: (addr stmt-var) = stmt->inouts
25049     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25050     89/<- %edi 0/r32/eax
25051     # zero inouts
25052     3d/compare-eax-and 0/imm32
25053     0f 84/jump-if-= $check-mu-populate-stmt:error-incorrect-inouts/disp32
25054 $check-mu-populate-stmt:get-length:
25055     # var length/esi: (addr stmt-var) = dest->next
25056     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
25057     89/<- %esi 0/r32/eax
25058     # 1 inout
25059     3d/compare-eax-and 0/imm32
25060     0f 84/jump-if-= $check-mu-populate-stmt:error-incorrect-inouts/disp32
25061     # > 2 inouts
25062     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
25063     3d/compare-eax-and 0/imm32
25064     0f 85/jump-if-!= $check-mu-populate-stmt:error-incorrect-inouts/disp32
25065 $check-mu-populate-stmt:check-target-type:
25066     # var target-type/ebx: (addr type-tree) = target->value->type
25067     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
25068     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
25069     89/<- %ebx 0/r32/eax
25070 $check-mu-populate-stmt:check-target-type-deref:
25071     # if (target->is-deref?) target-type = target-type->payload
25072     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
25073     3d/compare-eax-and 0/imm32/false
25074     {
25075       74/jump-if-= break/disp8
25076       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
25077       # if target-type->right is null, target-type = target-type->left
25078       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
25079       {
25080         75/jump-if-!= break/disp8
25081         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
25082       }
25083       89/<- %ebx 0/r32/eax
25084     }
25085 $check-mu-populate-stmt:check-target-type-addr:
25086     # if target-type is not addr, abort
25087     (is-mu-addr-type? %ebx)  # => eax
25088     3d/compare-eax-and 0/imm32/false
25089     0f 84/jump-if-= $check-mu-populate-stmt:error-invalid-target-type/disp32
25090     # if target-type->right is an atom, abort
25091     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
25092     89/<- %ebx 0/r32/eax
25093     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
25094     0f 85/jump-if-!= $check-mu-populate-stmt:error-invalid-target-type/disp32
25095 $check-mu-populate-stmt:check-target-type-handle:
25096     # if target-type->right->left is not handle, abort
25097     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
25098     (is-simple-mu-type? %eax 4)  # handle => eax
25099     3d/compare-eax-and 0/imm32/false
25100     0f 84/jump-if-= $check-mu-populate-stmt:error-invalid-target-type/disp32
25101     # if target-type->right->right is an atom, abort
25102     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
25103     89/<- %ebx 0/r32/eax
25104     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
25105     0f 85/jump-if-!= $check-mu-populate-stmt:error-invalid-target-type/disp32
25106 $check-mu-populate-stmt:check-target-type-array:
25107     # if target-type->right->right->left is not array, abort
25108     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
25109     (is-simple-mu-type? %eax 3)  # array => eax
25110     3d/compare-eax-and 0/imm32/false
25111     0f 84/jump-if-= $check-mu-populate-stmt:error-invalid-target-type/disp32
25112 $check-mu-populate-stmt:check-length-type:
25113     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
25114     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
25115     89/<- %ebx 0/r32/eax
25116     (is-simple-mu-type? %ebx 0)  # literal => eax
25117     3d/compare-eax-and 0/imm32/false
25118     75/jump-if-!= $check-mu-populate-stmt:end/disp8
25119     (is-simple-mu-type? %ebx 1)  # int => eax
25120     3d/compare-eax-and 0/imm32/false
25121     0f 84/jump-if-= $check-mu-populate-stmt:error-invalid-length-type/disp32
25122 $check-mu-populate-stmt:end:
25123     # . restore registers
25124     5f/pop-to-edi
25125     5e/pop-to-esi
25126     5b/pop-to-ebx
25127     58/pop-to-eax
25128     # . epilogue
25129     89/<- %esp 5/r32/ebp
25130     5d/pop-to-ebp
25131     c3/return
25132 
25133 $check-mu-populate-stmt:error-incorrect-inouts:
25134     (write-buffered *(ebp+0x10) "fn ")
25135     8b/-> *(ebp+0xc) 0/r32/eax
25136     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25137     (write-buffered *(ebp+0x10) %eax)
25138     (write-buffered *(ebp+0x10) ": stmt 'populate' must have two inouts\n")
25139     (flush *(ebp+0x10))
25140     (stop *(ebp+0x14) 1)
25141     # never gets here
25142 
25143 $check-mu-populate-stmt:error-too-many-outputs:
25144     (write-buffered *(ebp+0x10) "fn ")
25145     8b/-> *(ebp+0xc) 0/r32/eax
25146     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25147     (write-buffered *(ebp+0x10) %eax)
25148     (write-buffered *(ebp+0x10) ": stmt 'populate' must not have any outputs\n")
25149     (flush *(ebp+0x10))
25150     (stop *(ebp+0x14) 1)
25151     # never gets here
25152 
25153 $check-mu-populate-stmt:error-invalid-target-type:
25154     (write-buffered *(ebp+0x10) "fn ")
25155     8b/-> *(ebp+0xc) 0/r32/eax
25156     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25157     (write-buffered *(ebp+0x10) %eax)
25158     (write-buffered *(ebp+0x10) ": stmt populate: first inout '")
25159     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
25160     (lookup *eax *(eax+4))  # Var-name Var-name => eax
25161     (write-buffered *(ebp+0x10) %eax)
25162     (write-buffered *(ebp+0x10) "' must have type (addr handle array ...)\n")
25163     (flush *(ebp+0x10))
25164     (stop *(ebp+0x14) 1)
25165     # never gets here
25166 
25167 $check-mu-populate-stmt:error-invalid-length-type:
25168     (write-buffered *(ebp+0x10) "fn ")
25169     8b/-> *(ebp+0xc) 0/r32/eax
25170     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25171     (write-buffered *(ebp+0x10) %eax)
25172     (write-buffered *(ebp+0x10) ": stmt populate: second inout '")
25173     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
25174     (lookup *eax *(eax+4))  # Var-name Var-name => eax
25175     (write-buffered *(ebp+0x10) %eax)
25176     (write-buffered *(ebp+0x10) "' must be an int\n")
25177     (flush *(ebp+0x10))
25178     (stop *(ebp+0x14) 1)
25179     # never gets here
25180 
25181 check-mu-populate-stream-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
25182     # . prologue
25183     55/push-ebp
25184     89/<- %ebp 4/r32/esp
25185     # . save registers
25186     50/push-eax
25187     53/push-ebx
25188     56/push-esi
25189     57/push-edi
25190     # esi = stmt
25191     8b/-> *(ebp+8) 6/r32/esi
25192 $check-mu-populate-stream-stmt:check-for-output:
25193     # if stmt->outputs abort
25194     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
25195     3d/compare-eax-and 0/imm32
25196     0f 85/jump-if-!= $check-mu-populate-stream-stmt:error-too-many-outputs/disp32
25197 $check-mu-populate-stream-stmt:get-target:
25198     # var target/edi: (addr stmt-var) = stmt->inouts
25199     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25200     89/<- %edi 0/r32/eax
25201     # zero inouts
25202     3d/compare-eax-and 0/imm32
25203     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-incorrect-inouts/disp32
25204 $check-mu-populate-stream-stmt:get-length:
25205     # var length/esi: (addr stmt-var) = dest->next
25206     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
25207     89/<- %esi 0/r32/eax
25208     # 1 inout
25209     3d/compare-eax-and 0/imm32
25210     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-incorrect-inouts/disp32
25211     # > 2 inouts
25212     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
25213     3d/compare-eax-and 0/imm32
25214     0f 85/jump-if-!= $check-mu-populate-stream-stmt:error-incorrect-inouts/disp32
25215 $check-mu-populate-stream-stmt:check-target-type:
25216     # var target-type/ebx: (addr type-tree) = target->value->type
25217     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
25218     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
25219     89/<- %ebx 0/r32/eax
25220 $check-mu-populate-stream-stmt:check-target-type-deref:
25221     # if (target->is-deref?) target-type = target-type->payload
25222     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
25223     3d/compare-eax-and 0/imm32/false
25224     {
25225       74/jump-if-= break/disp8
25226       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
25227       # if target-type->right is null, target-type = target-type->left
25228       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
25229       {
25230         75/jump-if-!= break/disp8
25231         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
25232       }
25233       89/<- %ebx 0/r32/eax
25234     }
25235 $check-mu-populate-stream-stmt:check-target-type-addr:
25236     # if target-type is not addr, abort
25237     (is-mu-addr-type? %ebx)  # => eax
25238     3d/compare-eax-and 0/imm32/false
25239     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
25240     # if target-type->right is an atom, abort
25241     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
25242     89/<- %ebx 0/r32/eax
25243     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
25244     0f 85/jump-if-!= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
25245 $check-mu-populate-stream-stmt:check-target-type-handle:
25246     # if target-type->right->left is not handle, abort
25247     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
25248     (is-simple-mu-type? %eax 4)  # handle => eax
25249     3d/compare-eax-and 0/imm32/false
25250     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
25251     # if target-type->right->right is an atom, abort
25252     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
25253     89/<- %ebx 0/r32/eax
25254     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
25255     0f 85/jump-if-!= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
25256 $check-mu-populate-stream-stmt:check-target-type-stream:
25257     # if target-type->right->right->left is not stream, abort
25258     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
25259     (is-simple-mu-type? %eax 0xb)  # stream => eax
25260     3d/compare-eax-and 0/imm32/false
25261     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
25262 $check-mu-populate-stream-stmt:check-length-type:
25263     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
25264     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
25265     89/<- %ebx 0/r32/eax
25266     (is-simple-mu-type? %ebx 0)  # literal => eax
25267     3d/compare-eax-and 0/imm32/false
25268     75/jump-if-!= $check-mu-populate-stream-stmt:end/disp8
25269     (is-simple-mu-type? %ebx 1)  # int => eax
25270     3d/compare-eax-and 0/imm32/false
25271     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-invalid-length-type/disp32
25272 $check-mu-populate-stream-stmt:end:
25273     # . restore registers
25274     5f/pop-to-edi
25275     5e/pop-to-esi
25276     5b/pop-to-ebx
25277     58/pop-to-eax
25278     # . epilogue
25279     89/<- %esp 5/r32/ebp
25280     5d/pop-to-ebp
25281     c3/return
25282 
25283 $check-mu-populate-stream-stmt:error-incorrect-inouts:
25284     (write-buffered *(ebp+0x10) "fn ")
25285     8b/-> *(ebp+0xc) 0/r32/eax
25286     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25287     (write-buffered *(ebp+0x10) %eax)
25288     (write-buffered *(ebp+0x10) ": stmt 'populate-stream' must have two inouts\n")
25289     (flush *(ebp+0x10))
25290     (stop *(ebp+0x14) 1)
25291     # never gets here
25292 
25293 $check-mu-populate-stream-stmt:error-too-many-outputs:
25294     (write-buffered *(ebp+0x10) "fn ")
25295     8b/-> *(ebp+0xc) 0/r32/eax
25296     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25297     (write-buffered *(ebp+0x10) %eax)
25298     (write-buffered *(ebp+0x10) ": stmt 'populate-stream' must not have any outputs\n")
25299     (flush *(ebp+0x10))
25300     (stop *(ebp+0x14) 1)
25301     # never gets here
25302 
25303 $check-mu-populate-stream-stmt:error-invalid-target-type:
25304     (write-buffered *(ebp+0x10) "fn ")
25305     8b/-> *(ebp+0xc) 0/r32/eax
25306     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25307     (write-buffered *(ebp+0x10) %eax)
25308     (write-buffered *(ebp+0x10) ": stmt populate-stream: first inout '")
25309     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
25310     (lookup *eax *(eax+4))  # Var-name Var-name => eax
25311     (write-buffered *(ebp+0x10) %eax)
25312     (write-buffered *(ebp+0x10) "' must have type (addr handle stream ...)\n")
25313     (flush *(ebp+0x10))
25314     (stop *(ebp+0x14) 1)
25315     # never gets here
25316 
25317 $check-mu-populate-stream-stmt:error-invalid-length-type:
25318     (write-buffered *(ebp+0x10) "fn ")
25319     8b/-> *(ebp+0xc) 0/r32/eax
25320     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25321     (write-buffered *(ebp+0x10) %eax)
25322     (write-buffered *(ebp+0x10) ": stmt populate-stream: second inout '")
25323     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
25324     (lookup *eax *(eax+4))  # Var-name Var-name => eax
25325     (write-buffered *(ebp+0x10) %eax)
25326     (write-buffered *(ebp+0x10) "' must be an int\n")
25327     (flush *(ebp+0x10))
25328     (stop *(ebp+0x14) 1)
25329     # never gets here
25330 
25331 check-mu-read-from-stream-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
25332     # . prologue
25333     55/push-ebp
25334     89/<- %ebp 4/r32/esp
25335     # . save registers
25336     50/push-eax
25337     51/push-ecx
25338     52/push-edx
25339     53/push-ebx
25340     56/push-esi
25341     57/push-edi
25342     # esi = stmt
25343     8b/-> *(ebp+8) 6/r32/esi
25344     # - check for 0 inouts
25345     # var base/ecx: (addr var) = stmt->inouts->value
25346     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25347 $check-mu-read-from-stream-stmt:check-no-inouts:
25348     3d/compare-eax-and 0/imm32
25349     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-too-few-inouts/disp32
25350     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
25351     89/<- %ecx 0/r32/eax
25352     # - check base type is (addr stream T)
25353     # var base-type/ebx: (addr type-tree) = lookup(base->type)
25354     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
25355     89/<- %ebx 0/r32/eax
25356 $check-mu-read-from-stream-stmt:check-base-is-compound:
25357     # if base-type is an atom, abort
25358     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
25359     0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-invalid-base-type/disp32
25360 $check-mu-read-from-stream-stmt:check-base-is-addr:
25361     # if type->left not addr, abort
25362     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
25363     (is-simple-mu-type? %eax 2)  # addr => eax
25364     3d/compare-eax-and 0/imm32/false
25365     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-invalid-base-type/disp32
25366 $check-mu-read-from-stream-stmt:check-base-is-addr-to-stream:
25367     # base-type = base-type->right
25368     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
25369     89/<- %ebx 0/r32/eax
25370     # ensure base-type->left == stream
25371     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
25372     (is-simple-mu-type? %eax 0xb)  # stream => eax
25373     3d/compare-eax-and 0/imm32/false
25374     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-invalid-base-type/disp32
25375     # - check target type is (addr T)
25376     # var target/ecx: (addr stmt-var) = stmt->inouts->next->value
25377     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25378     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
25379 $check-mu-read-from-stream-stmt:check-single-inout:
25380     3d/compare-eax-and 0/imm32
25381     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-too-few-inouts/disp32
25382     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
25383     89/<- %ecx 0/r32/eax
25384     # var target-type/edx: (addr type-tree)
25385     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
25386     89/<- %edx 0/r32/eax
25387     # if target-type is an atom, it must be a literal or int
25388 $check-mu-read-from-stream-stmt:check-target-is-compound:
25389     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
25390     0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-target-type-not-address/disp32
25391 $check-mu-read-from-stream-stmt:check-target-type:
25392     # target type must start with (addr ...)
25393     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
25394     (is-simple-mu-type? %eax 2)  # addr => eax
25395     3d/compare-eax-and 0/imm32/false
25396     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-target-type-not-address/disp32
25397     # if tail(base-type) != tail(target-type) abort
25398     (type-tail %ebx)  # => eax
25399     89/<- %ebx 0/r32/eax
25400     (type-tail %edx)  # => eax
25401     (type-equal? %ebx %eax)  # => eax
25402     3d/compare-eax-and 0/imm32/false
25403     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-invalid-target-type/disp32
25404 $check-mu-read-from-stream-stmt:check-too-many-inouts:
25405     # - check for too many inouts
25406     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25407     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
25408     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
25409     3d/compare-eax-and 0/imm32/false
25410     0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-too-many-inouts/disp32
25411 $check-mu-read-from-stream-stmt:check-unexpected-output:
25412     # - check for any output
25413     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
25414     3d/compare-eax-and 0/imm32/false
25415     0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-unexpected-output/disp32
25416 $check-mu-read-from-stream-stmt:end:
25417     # . restore registers
25418     5f/pop-to-edi
25419     5e/pop-to-esi
25420     5b/pop-to-ebx
25421     5a/pop-to-edx
25422     59/pop-to-ecx
25423     58/pop-to-eax
25424     # . epilogue
25425     89/<- %esp 5/r32/ebp
25426     5d/pop-to-ebp
25427     c3/return
25428 
25429 $check-mu-read-from-stream-stmt:error-invalid-base-type:
25430     (write-buffered *(ebp+0x10) "fn ")
25431     8b/-> *(ebp+0xc) 0/r32/eax
25432     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25433     (write-buffered *(ebp+0x10) %eax)
25434     (write-buffered *(ebp+0x10) ": stmt read-from-stream: var '")
25435     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
25436     (write-buffered *(ebp+0x10) %eax)
25437     (write-buffered *(ebp+0x10) "' must be an addr to a stream\n")
25438     (flush *(ebp+0x10))
25439     (stop *(ebp+0x14) 1)
25440     # never gets here
25441 
25442 $check-mu-read-from-stream-stmt:error-too-few-inouts:
25443     (write-buffered *(ebp+0x10) "fn ")
25444     8b/-> *(ebp+0xc) 0/r32/eax
25445     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25446     (write-buffered *(ebp+0x10) %eax)
25447     (write-buffered *(ebp+0x10) ": stmt read-from-stream: too few inouts (2 required)\n")
25448     (flush *(ebp+0x10))
25449     (stop *(ebp+0x14) 1)
25450     # never gets here
25451 
25452 $check-mu-read-from-stream-stmt:error-target-type-not-address:
25453     (write-buffered *(ebp+0x10) "fn ")
25454     8b/-> *(ebp+0xc) 0/r32/eax
25455     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25456     (write-buffered *(ebp+0x10) %eax)
25457     (write-buffered *(ebp+0x10) ": stmt read-from-stream: target '")
25458     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
25459     (write-buffered *(ebp+0x10) %eax)
25460     (write-buffered *(ebp+0x10) "' must be an addr\n")
25461     (flush *(ebp+0x10))
25462     (stop *(ebp+0x14) 1)
25463     # never gets here
25464 
25465 $check-mu-read-from-stream-stmt:error-invalid-target-type:
25466     (write-buffered *(ebp+0x10) "fn ")
25467     8b/-> *(ebp+0xc) 0/r32/eax
25468     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25469     (write-buffered *(ebp+0x10) %eax)
25470     (write-buffered *(ebp+0x10) ": stmt read-from-stream: second inout '")
25471     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
25472     (write-buffered *(ebp+0x10) %eax)
25473     (write-buffered *(ebp+0x10) "' does not have the right type\n")
25474     (flush *(ebp+0x10))
25475     (stop *(ebp+0x14) 1)
25476     # never gets here
25477 
25478 $check-mu-read-from-stream-stmt:error-too-many-inouts:
25479     (write-buffered *(ebp+0x10) "fn ")
25480     8b/-> *(ebp+0xc) 0/r32/eax
25481     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25482     (write-buffered *(ebp+0x10) %eax)
25483     (write-buffered *(ebp+0x10) ": stmt read-from-stream: too many inouts (2 required)\n")
25484     (flush *(ebp+0x10))
25485     (stop *(ebp+0x14) 1)
25486     # never gets here
25487 
25488 $check-mu-read-from-stream-stmt:error-unexpected-output:
25489     (write-buffered *(ebp+0x10) "fn ")
25490     8b/-> *(ebp+0xc) 0/r32/eax
25491     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25492     (write-buffered *(ebp+0x10) %eax)
25493     (write-buffered *(ebp+0x10) ": stmt read-from-stream: unexpected output\n")
25494     (flush *(ebp+0x10))
25495     (stop *(ebp+0x14) 1)
25496     # never gets here
25497 
25498 check-mu-write-to-stream-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
25499     # . prologue
25500     55/push-ebp
25501     89/<- %ebp 4/r32/esp
25502     # . save registers
25503     50/push-eax
25504     51/push-ecx
25505     52/push-edx
25506     53/push-ebx
25507     56/push-esi
25508     57/push-edi
25509     # esi = stmt
25510     8b/-> *(ebp+8) 6/r32/esi
25511     # - check for 0 inouts
25512     # var base/ecx: (addr var) = stmt->inouts->value
25513     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25514 $check-mu-write-to-stream-stmt:check-no-inouts:
25515     3d/compare-eax-and 0/imm32
25516     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-too-few-inouts/disp32
25517     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
25518     89/<- %ecx 0/r32/eax
25519     # - check base type is (addr stream T)
25520     # var base-type/ebx: (addr type-tree) = lookup(base->type)
25521     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
25522     89/<- %ebx 0/r32/eax
25523 $check-mu-write-to-stream-stmt:check-base-is-compound:
25524     # if base-type is an atom, abort
25525     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
25526     0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-invalid-base-type/disp32
25527 $check-mu-write-to-stream-stmt:check-base-is-addr:
25528     # if type->left not addr, abort
25529     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
25530     (is-simple-mu-type? %eax 2)  # addr => eax
25531     3d/compare-eax-and 0/imm32/false
25532     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-invalid-base-type/disp32
25533 $check-mu-write-to-stream-stmt:check-base-is-addr-to-stream:
25534     # base-type = base-type->right
25535     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
25536     89/<- %ebx 0/r32/eax
25537     # ensure base-type->left == stream
25538     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
25539     (is-simple-mu-type? %eax 0xb)  # stream => eax
25540     3d/compare-eax-and 0/imm32/false
25541     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-invalid-base-type/disp32
25542     # - check target type is (addr T)
25543     # var target/ecx: (addr stmt-var) = stmt->inouts->next->value
25544     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25545     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
25546 $check-mu-write-to-stream-stmt:check-single-inout:
25547     3d/compare-eax-and 0/imm32
25548     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-too-few-inouts/disp32
25549     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
25550     89/<- %ecx 0/r32/eax
25551     # var target-type/edx: (addr type-tree)
25552     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
25553     89/<- %edx 0/r32/eax
25554     # if target-type is an atom, it must be a literal or int
25555 $check-mu-write-to-stream-stmt:check-target-is-compound:
25556     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
25557     0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-target-type-not-address/disp32
25558 $check-mu-write-to-stream-stmt:check-target-type:
25559     # target type must start with (addr ...)
25560     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
25561     (is-simple-mu-type? %eax 2)  # addr => eax
25562     3d/compare-eax-and 0/imm32/false
25563     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-target-type-not-address/disp32
25564     # if tail(base-type) != tail(target-type) abort
25565     (type-tail %ebx)  # => eax
25566     89/<- %ebx 0/r32/eax
25567     (type-tail %edx)  # => eax
25568     (type-equal? %ebx %eax)  # => eax
25569     3d/compare-eax-and 0/imm32/false
25570     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-invalid-target-type/disp32
25571 $check-mu-write-to-stream-stmt:check-too-many-inouts:
25572     # - check for too many inouts
25573     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25574     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
25575     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
25576     3d/compare-eax-and 0/imm32/false
25577     0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-too-many-inouts/disp32
25578 $check-mu-write-to-stream-stmt:check-unexpected-output:
25579     # - check for any output
25580     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
25581     3d/compare-eax-and 0/imm32/false
25582     0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-unexpected-output/disp32
25583 $check-mu-write-to-stream-stmt:end:
25584     # . restore registers
25585     5f/pop-to-edi
25586     5e/pop-to-esi
25587     5b/pop-to-ebx
25588     5a/pop-to-edx
25589     59/pop-to-ecx
25590     58/pop-to-eax
25591     # . epilogue
25592     89/<- %esp 5/r32/ebp
25593     5d/pop-to-ebp
25594     c3/return
25595 
25596 $check-mu-write-to-stream-stmt:error-invalid-base-type:
25597     (write-buffered *(ebp+0x10) "fn ")
25598     8b/-> *(ebp+0xc) 0/r32/eax
25599     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25600     (write-buffered *(ebp+0x10) %eax)
25601     (write-buffered *(ebp+0x10) ": stmt write-to-stream: var '")
25602     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
25603     (write-buffered *(ebp+0x10) %eax)
25604     (write-buffered *(ebp+0x10) "' must be an addr to a stream\n")
25605     (flush *(ebp+0x10))
25606     (stop *(ebp+0x14) 1)
25607     # never gets here
25608 
25609 $check-mu-write-to-stream-stmt:error-too-few-inouts:
25610     (write-buffered *(ebp+0x10) "fn ")
25611     8b/-> *(ebp+0xc) 0/r32/eax
25612     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25613     (write-buffered *(ebp+0x10) %eax)
25614     (write-buffered *(ebp+0x10) ": stmt write-to-stream: too few inouts (2 required)\n")
25615     (flush *(ebp+0x10))
25616     (stop *(ebp+0x14) 1)
25617     # never gets here
25618 
25619 $check-mu-write-to-stream-stmt:error-target-type-not-address:
25620     (write-buffered *(ebp+0x10) "fn ")
25621     8b/-> *(ebp+0xc) 0/r32/eax
25622     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25623     (write-buffered *(ebp+0x10) %eax)
25624     (write-buffered *(ebp+0x10) ": stmt write-to-stream: target '")
25625     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
25626     (write-buffered *(ebp+0x10) %eax)
25627     (write-buffered *(ebp+0x10) "' must be an addr\n")
25628     (flush *(ebp+0x10))
25629     (stop *(ebp+0x14) 1)
25630     # never gets here
25631 
25632 $check-mu-write-to-stream-stmt:error-invalid-target-type:
25633     (write-buffered *(ebp+0x10) "fn ")
25634     8b/-> *(ebp+0xc) 0/r32/eax
25635     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25636     (write-buffered *(ebp+0x10) %eax)
25637     (write-buffered *(ebp+0x10) ": stmt write-to-stream: second inout '")
25638     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
25639     (write-buffered *(ebp+0x10) %eax)
25640     (write-buffered *(ebp+0x10) "' does not have the right type\n")
25641     (flush *(ebp+0x10))
25642     (stop *(ebp+0x14) 1)
25643     # never gets here
25644 
25645 $check-mu-write-to-stream-stmt:error-too-many-inouts:
25646     (write-buffered *(ebp+0x10) "fn ")
25647     8b/-> *(ebp+0xc) 0/r32/eax
25648     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25649     (write-buffered *(ebp+0x10) %eax)
25650     (write-buffered *(ebp+0x10) ": stmt write-to-stream: too many inouts (2 required)\n")
25651     (flush *(ebp+0x10))
25652     (stop *(ebp+0x14) 1)
25653     # never gets here
25654 
25655 $check-mu-write-to-stream-stmt:error-unexpected-output:
25656     (write-buffered *(ebp+0x10) "fn ")
25657     8b/-> *(ebp+0xc) 0/r32/eax
25658     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25659     (write-buffered *(ebp+0x10) %eax)
25660     (write-buffered *(ebp+0x10) ": stmt write-to-stream: unexpected output\n")
25661     (flush *(ebp+0x10))
25662     (stop *(ebp+0x14) 1)
25663     # never gets here
25664 
25665 check-mu-convert-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
25666     # . prologue
25667     55/push-ebp
25668     89/<- %ebp 4/r32/esp
25669     # . save registers
25670     50/push-eax
25671     51/push-ecx
25672     52/push-edx
25673     56/push-esi
25674     57/push-edi
25675 $check-mu-convert-stmt:get-output:
25676     # esi = stmt
25677     8b/-> *(ebp+8) 6/r32/esi
25678     # var output/edi: (addr stmt-var) = stmt->outputs
25679     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
25680     89/<- %edi 0/r32/eax
25681     # zero outputs
25682     3d/compare-eax-and 0/imm32
25683     0f 84/jump-if-= $check-mu-convert-stmt:error-no-output/disp32
25684     # > 1 output
25685     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
25686     3d/compare-eax-and 0/imm32
25687     0f 85/jump-if-!= $check-mu-convert-stmt:error-too-many-outputs/disp32
25688 $check-mu-convert-stmt:get-inout:
25689     # var inout/esi: (addr stmt-var) = stmt->inouts
25690     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25691     89/<- %esi 0/r32/eax
25692     # zero inouts
25693     3d/compare-eax-and 0/imm32
25694     0f 84/jump-if-= $check-mu-convert-stmt:error-no-inout/disp32
25695     # > 1 inout
25696     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
25697     3d/compare-eax-and 0/imm32
25698     0f 85/jump-if-!= $check-mu-convert-stmt:error-too-many-inouts/disp32
25699 $check-mu-convert-stmt:types:
25700     # var inout-type/ecx: (addr type-tree) = inout->value->type
25701     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
25702     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
25703     89/<- %ecx 0/r32/eax
25704     # if (inout->is-deref?) inout-type = inout-type->payload
25705     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
25706     3d/compare-eax-and 0/imm32/false
25707     {
25708       74/jump-if-= break/disp8
25709       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
25710       # if inout-type->right is null, t = inout-type->left
25711       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
25712       {
25713         75/jump-if-!= break/disp8
25714         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
25715       }
25716       89/<- %ecx 0/r32/eax
25717     }
25718     # if input is not int or float, abort
25719     {
25720       (is-simple-mu-type? %ecx 1)  # int => eax
25721       3d/compare-eax-and 0/imm32/false
25722       75/jump-if-!= break/disp8
25723       (is-simple-mu-type? %ecx 0xf)  # float => eax
25724       3d/compare-eax-and 0/imm32/false
25725       75/jump-if-!= break/disp8
25726       e9/jump $check-mu-convert-stmt:error-invalid-inout-type/disp32
25727     }
25728     # if output not in register, abort
25729     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
25730     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
25731     3d/compare-eax-and 0/imm32
25732     0f 84/jump-if-= $check-mu-convert-stmt:error-output-not-in-register/disp32
25733     # var output-type/edx: (addr type-tree) = output->value->type
25734     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
25735     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
25736     89/<- %edx 0/r32/eax
25737     # if output is not int or float, abort
25738     {
25739       (is-simple-mu-type? %edx 1)  # int => eax
25740       3d/compare-eax-and 0/imm32/false
25741       75/jump-if-!= break/disp8
25742       (is-simple-mu-type? %edx 0xf)  # float => eax
25743       3d/compare-eax-and 0/imm32/false
25744       75/jump-if-!= break/disp8
25745       e9/jump $check-mu-convert-stmt:error-invalid-output-type/disp32
25746     }
25747     # if both are ints, abort
25748     {
25749       (is-simple-mu-type? %edx 1)  # int => eax
25750       3d/compare-eax-and 0/imm32/false
25751       74/jump-if-= break/disp8
25752       (is-simple-mu-type? %ecx 1)  # int => eax
25753       3d/compare-eax-and 0/imm32/false
25754       74/jump-if-= break/disp8
25755       e9/jump $check-mu-convert-stmt:error-int-to-int/disp32
25756     }
25757     # if both are floats, abort
25758     {
25759       (is-simple-mu-type? %edx 0xf)  # float => eax
25760       3d/compare-eax-and 0/imm32/false
25761       74/jump-if-= break/disp8
25762       (is-simple-mu-type? %ecx 0xf)  # float => eax
25763       3d/compare-eax-and 0/imm32/false
25764       74/jump-if-= break/disp8
25765       e9/jump $check-mu-convert-stmt:error-float-to-float/disp32
25766     }
25767 $check-mu-convert-stmt:end:
25768     # . restore registers
25769     5f/pop-to-edi
25770     5e/pop-to-esi
25771     5a/pop-to-edx
25772     59/pop-to-ecx
25773     58/pop-to-eax
25774     # . epilogue
25775     89/<- %esp 5/r32/ebp
25776     5d/pop-to-ebp
25777     c3/return
25778 
25779 $check-mu-convert-stmt:error-no-inout:
25780     (write-buffered *(ebp+0x10) "fn ")
25781     8b/-> *(ebp+0xc) 0/r32/eax
25782     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25783     (write-buffered *(ebp+0x10) %eax)
25784     (write-buffered *(ebp+0x10) ": stmt 'convert' expects an inout\n")
25785     (flush *(ebp+0x10))
25786     (stop *(ebp+0x14) 1)
25787     # never gets here
25788 
25789 $check-mu-convert-stmt:error-too-many-inouts:
25790     (write-buffered *(ebp+0x10) "fn ")
25791     8b/-> *(ebp+0xc) 0/r32/eax
25792     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25793     (write-buffered *(ebp+0x10) %eax)
25794     (write-buffered *(ebp+0x10) ": stmt 'convert' must have just one inout\n")
25795     (flush *(ebp+0x10))
25796     (stop *(ebp+0x14) 1)
25797     # never gets here
25798 
25799 $check-mu-convert-stmt:error-no-output:
25800     (write-buffered *(ebp+0x10) "fn ")
25801     8b/-> *(ebp+0xc) 0/r32/eax
25802     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25803     (write-buffered *(ebp+0x10) %eax)
25804     (write-buffered *(ebp+0x10) ": stmt 'convert' expects an output\n")
25805     (flush *(ebp+0x10))
25806     (stop *(ebp+0x14) 1)
25807     # never gets here
25808 
25809 $check-mu-convert-stmt:error-output-not-in-register:
25810     (write-buffered *(ebp+0x10) "fn ")
25811     8b/-> *(ebp+0xc) 0/r32/eax
25812     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25813     (write-buffered *(ebp+0x10) %eax)
25814     (write-buffered *(ebp+0x10) ": stmt convert: output '")
25815     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
25816     (lookup *eax *(eax+4))  # Var-name Var-name => eax
25817     (write-buffered *(ebp+0x10) %eax)
25818     (write-buffered *(ebp+0x10) "' not in a register\n")
25819     (flush *(ebp+0x10))
25820     (stop *(ebp+0x14) 1)
25821     # never gets here
25822 
25823 $check-mu-convert-stmt:error-too-many-outputs:
25824     (write-buffered *(ebp+0x10) "fn ")
25825     8b/-> *(ebp+0xc) 0/r32/eax
25826     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25827     (write-buffered *(ebp+0x10) %eax)
25828     (write-buffered *(ebp+0x10) ": stmt 'convert' must have just one output\n")
25829     (flush *(ebp+0x10))
25830     (stop *(ebp+0x14) 1)
25831     # never gets here
25832 
25833 $check-mu-convert-stmt:error-invalid-inout-type:
25834     (write-buffered *(ebp+0x10) "fn ")
25835     8b/-> *(ebp+0xc) 0/r32/eax
25836     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25837     (write-buffered *(ebp+0x10) %eax)
25838     (write-buffered *(ebp+0x10) ": stmt convert: inout '")
25839     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
25840     (lookup *eax *(eax+4))  # Var-name Var-name => eax
25841     (write-buffered *(ebp+0x10) %eax)
25842     (write-buffered *(ebp+0x10) "' must be an int or float\n")
25843     (flush *(ebp+0x10))
25844     (stop *(ebp+0x14) 1)
25845     # never gets here
25846 
25847 $check-mu-convert-stmt:error-invalid-output-type:
25848     (write-buffered *(ebp+0x10) "fn ")
25849     8b/-> *(ebp+0xc) 0/r32/eax
25850     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25851     (write-buffered *(ebp+0x10) %eax)
25852     (write-buffered *(ebp+0x10) ": stmt convert: output '")
25853     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
25854     (lookup *eax *(eax+4))  # Var-name Var-name => eax
25855     (write-buffered *(ebp+0x10) %eax)
25856     (write-buffered *(ebp+0x10) "' must be an int or float\n")
25857     (flush *(ebp+0x10))
25858     (stop *(ebp+0x14) 1)
25859     # never gets here
25860 
25861 $check-mu-convert-stmt:error-int-to-int:
25862     (write-buffered *(ebp+0x10) "fn ")
25863     8b/-> *(ebp+0xc) 0/r32/eax
25864     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25865     (write-buffered *(ebp+0x10) %eax)
25866     (write-buffered *(ebp+0x10) ": stmt convert: no need to convert int to int\n")
25867     (flush *(ebp+0x10))
25868     (stop *(ebp+0x14) 1)
25869     # never gets here
25870 
25871 $check-mu-convert-stmt:error-float-to-float:
25872     (write-buffered *(ebp+0x10) "fn ")
25873     8b/-> *(ebp+0xc) 0/r32/eax
25874     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25875     (write-buffered *(ebp+0x10) %eax)
25876     (write-buffered *(ebp+0x10) ": stmt convert: no need to convert float to float\n")
25877     (flush *(ebp+0x10))
25878     (stop *(ebp+0x14) 1)
25879     # never gets here
25880 
25881 check-mu-call:  # stmt: (addr stmt), callee: (addr function), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
25882     # . prologue
25883     55/push-ebp
25884     89/<- %ebp 4/r32/esp
25885     # var type-parameters: (addr table (handle array byte) (addr type-tree) 8)
25886     68/push 0/imm32
25887     # var type-parameters-storage: (table (handle array byte) (addr type-tree) 8)
25888     81 5/subop/subtract %esp 0x60/imm32
25889     68/push 0x60/imm32/size
25890     68/push 0/imm32/read
25891     68/push 0/imm32/write
25892     # save a pointer to type-parameters-storage at type-parameters
25893     89/<- *(ebp-4) 4/r32/esp
25894     (clear-stream *(ebp-4))
25895     # . save registers
25896     50/push-eax
25897     51/push-ecx
25898     52/push-edx
25899     53/push-ebx
25900     56/push-esi
25901     57/push-edi
25902     # esi = stmt
25903     8b/-> *(ebp+8) 6/r32/esi
25904     # edi = callee
25905     8b/-> *(ebp+0xc) 7/r32/edi
25906     # var inouts/ecx: (addr stmt-var) = lookup(stmt->inouts)
25907     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25908     89/<- %ecx 0/r32/eax
25909     # var expected/edx: (addr list var) = lookup(f->inouts)
25910     (lookup *(edi+8) *(edi+0xc))  # Function-inouts Function-inouts => eax
25911     89/<- %edx 0/r32/eax
25912     {
25913 $check-mu-call:check-for-inouts:
25914       # if (inouts == 0) break
25915       81 7/subop/compare %ecx 0/imm32
25916       0f 84/jump-if-= break/disp32
25917       # if (expected == 0) error
25918       81 7/subop/compare %edx 0/imm32
25919       0f 84/jump-if-= break/disp32
25920 $check-mu-call:check-null-addr:
25921       # if (inouts->value->name == "0") continue
25922       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
25923       (lookup *eax *(eax+4))  # Var-name Var-name => eax
25924       (string-equal? %eax "0")  # => eax
25925       3d/compare-eax-and 0/imm32/false
25926       0f 85/jump-if-!= $check-mu-call:continue-to-next-inout/disp32
25927 $check-mu-call:check-inout-type:
25928       # var t/ebx: (addr type-tree) = inouts->value->type
25929       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
25930       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
25931       89/<- %ebx 0/r32/eax
25932       # if (inouts->is-deref?) t = t->right
25933       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
25934       {
25935         74/jump-if-= break/disp8
25936         (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
25937         89/<- %ebx 0/r32/eax
25938         # if t->right is null, t = t->left
25939         81 7/subop/compare *(ebx+0xc) 0/imm32  # Type-tree-right
25940         75/jump-if-!= break/disp8
25941         (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
25942         89/<- %ebx 0/r32/eax
25943       }
25944       # var v2/eax: (addr v) = lookup(expected->value)
25945       (lookup *edx *(edx+4))  # List-value List-value => eax
25946       # var t2/eax: (addr type-tree) = lookup(v2->type)
25947       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
25948       # if (t != t2) error
25949       (type-match? %eax %ebx *(ebp-4))  # => eax
25950       3d/compare-eax-and 0/imm32/false
25951       {
25952         0f 85/jump-if-!= break/disp32
25953         (write-buffered *(ebp+0x14) "fn ")
25954         8b/-> *(ebp+0x10) 0/r32/eax
25955         (lookup *eax *(eax+4))  # Function-name Function-name => eax
25956         (write-buffered *(ebp+0x14) %eax)
25957         (write-buffered *(ebp+0x14) ": call ")
25958         (lookup *edi *(edi+4))  # Function-name Function-name => eax
25959         (write-buffered *(ebp+0x14) %eax)
25960         (write-buffered *(ebp+0x14) ": type for inout '")
25961         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
25962         (lookup *eax *(eax+4))  # Var-name Var-name => eax
25963         (write-buffered *(ebp+0x14) %eax)
25964         (write-buffered *(ebp+0x14) "' is not right\n")
25965         (flush *(ebp+0x14))
25966         (stop *(ebp+0x18) 1)
25967       }
25968 $check-mu-call:continue-to-next-inout:
25969       # inouts = lookup(inouts->next)
25970       (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
25971       89/<- %ecx 0/r32/eax
25972       # expected = lookup(expected->next)
25973       (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
25974       89/<- %edx 0/r32/eax
25975       #
25976       e9/jump loop/disp32
25977     }
25978 $check-mu-call:check-inout-count:
25979     # if (inouts == expected) proceed
25980     39/compare %ecx 2/r32/edx
25981     {
25982       0f 84/jump-if-= break/disp32
25983       # exactly one of the two is null
25984       # if (inouts == 0) error("too many inouts")
25985       {
25986         81 7/subop/compare %ecx 0/imm32
25987         0f 84/jump-if-= break/disp32
25988         (write-buffered *(ebp+0x14) "fn ")
25989         8b/-> *(ebp+0x10) 0/r32/eax
25990         (lookup *eax *(eax+4))  # Function-name Function-name => eax
25991         (write-buffered *(ebp+0x14) %eax)
25992         (write-buffered *(ebp+0x14) ": call ")
25993         (lookup *edi *(edi+4))  # Function-name Function-name => eax
25994         (write-buffered *(ebp+0x14) %eax)
25995         (write-buffered *(ebp+0x14) ": too many inouts\n")
25996         (flush *(ebp+0x14))
25997         (stop *(ebp+0x18) 1)
25998       }
25999       # if (expected == 0) error("too few inouts")
26000       {
26001         81 7/subop/compare %edx 0/imm32
26002         0f 84/jump-if-= break/disp32
26003         (write-buffered *(ebp+0x14) "fn ")
26004         8b/-> *(ebp+0x10) 0/r32/eax
26005         (lookup *eax *(eax+4))  # Function-name Function-name => eax
26006         (write-buffered *(ebp+0x14) %eax)
26007         (write-buffered *(ebp+0x14) ": call ")
26008         (lookup *edi *(edi+4))  # Function-name Function-name => eax
26009         (write-buffered *(ebp+0x14) %eax)
26010         (write-buffered *(ebp+0x14) ": too few inouts\n")
26011         (flush *(ebp+0x14))
26012         (stop *(ebp+0x18) 1)
26013       }
26014     }
26015 $check-mu-call:check-outputs:
26016     # var outputs/ecx: (addr stmt-var) = lookup(stmt->outputs)
26017     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
26018     89/<- %ecx 0/r32/eax
26019     # var expected/edx: (addr list var) = lookup(f->outputs)
26020     (lookup *(edi+0x10) *(edi+0x14))  # Function-outputs Function-outputs => eax
26021     89/<- %edx 0/r32/eax
26022     {
26023 $check-mu-call:check-for-outputs:
26024       # if (outputs == 0) break
26025       81 7/subop/compare %ecx 0/imm32
26026       0f 84/jump-if-= break/disp32
26027       # if (expected == 0) error
26028       81 7/subop/compare %edx 0/imm32
26029       0f 84/jump-if-= break/disp32
26030 $check-mu-call:check-output-type:
26031       # var v/eax: (addr v) = lookup(outputs->value)
26032       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
26033       # var t/ebx: (addr type-tree) = lookup(v->type)
26034       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
26035       89/<- %ebx 0/r32/eax
26036       # if (outputs->is-deref?) t = t->right  # TODO: check that t->left is an addr
26037       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
26038       {
26039         74/jump-if-= break/disp8
26040         (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
26041         89/<- %ebx 0/r32/eax
26042       }
26043       # var v2/eax: (addr v) = lookup(expected->value)
26044       (lookup *edx *(edx+4))  # List-value List-value => eax
26045       # var t2/eax: (addr type-tree) = lookup(v2->type)
26046       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
26047       # if (t != t2) error
26048       (type-match? %eax %ebx *(ebp-4))  # => eax
26049       3d/compare-eax-and 0/imm32/false
26050       {
26051         0f 85/jump-if-!= break/disp32
26052         (write-buffered *(ebp+0x14) "fn ")
26053         8b/-> *(ebp+0x10) 0/r32/eax
26054         (lookup *eax *(eax+4))  # Function-name Function-name => eax
26055         (write-buffered *(ebp+0x14) %eax)
26056         (write-buffered *(ebp+0x14) ": call ")
26057         (lookup *edi *(edi+4))  # Function-name Function-name => eax
26058         (write-buffered *(ebp+0x14) %eax)
26059         (write-buffered *(ebp+0x14) ": type for output '")
26060         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
26061         (lookup *eax *(eax+4))  # Var-name Var-name => eax
26062         (write-buffered *(ebp+0x14) %eax)
26063         (write-buffered *(ebp+0x14) "' is not right\n")
26064         (flush *(ebp+0x14))
26065         (stop *(ebp+0x18) 1)
26066       }
26067 $check-mu-call:check-output-register:
26068       # var v/eax: (addr v) = lookup(outputs->value)
26069       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
26070       # var r/ebx: (addr array byte) = lookup(v->register)
26071       (lookup *(eax+18) *(eax+0x1c))  # Var-register Var-register => eax
26072       89/<- %ebx 0/r32/eax
26073       # if (r == 0) error
26074       3d/compare-eax-and 0/imm32
26075       {
26076         0f 85/jump-if-!= break/disp32
26077         (write-buffered *(ebp+0x14) "fn ")
26078         8b/-> *(ebp+0x10) 0/r32/eax
26079         (lookup *eax *(eax+4))  # Function-name Function-name => eax
26080         (write-buffered *(ebp+0x14) %eax)
26081         (write-buffered *(ebp+0x14) ": call ")
26082         (lookup *edi *(edi+4))  # Function-name Function-name => eax
26083         (write-buffered *(ebp+0x14) %eax)
26084         (write-buffered *(ebp+0x14) ": output '")
26085         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
26086         (lookup *eax *(eax+4))  # Var-name Var-name => eax
26087         (write-buffered *(ebp+0x14) %eax)
26088         (write-buffered *(ebp+0x14) "' is not in a register\n")
26089         (flush *(ebp+0x14))
26090         (stop *(ebp+0x18) 1)
26091       }
26092       # var v2/eax: (addr v) = lookup(expected->value)
26093       (lookup *edx *(edx+4))  # Stmt-var-value Stmt-var-value => eax
26094       # var r2/eax: (addr array byte) = lookup(v2->register)
26095       (lookup *(eax+18) *(eax+0x1c))  # Var-register Var-register => eax
26096       # if (r != r2) error
26097       (string-equal? %eax %ebx)  # => eax
26098       3d/compare-eax-and 0/imm32/false
26099       {
26100         0f 85/jump-if-!= break/disp32
26101         (write-buffered *(ebp+0x14) "fn ")
26102         8b/-> *(ebp+0x10) 0/r32/eax
26103         (lookup *eax *(eax+4))  # Function-name Function-name => eax
26104         (write-buffered *(ebp+0x14) %eax)
26105         (write-buffered *(ebp+0x14) ": call ")
26106         (lookup *edi *(edi+4))  # Function-name Function-name => eax
26107         (write-buffered *(ebp+0x14) %eax)
26108         (write-buffered *(ebp+0x14) ": register for output '")
26109         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
26110         (lookup *eax *(eax+4))  # Var-name Var-name => eax
26111         (write-buffered *(ebp+0x14) %eax)
26112         (write-buffered *(ebp+0x14) "' is not right\n")
26113         (flush *(ebp+0x14))
26114         (stop *(ebp+0x18) 1)
26115       }
26116 $check-mu-call:continue-to-next-output:
26117       # outputs = lookup(outputs->next)
26118       (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
26119       89/<- %ecx 0/r32/eax
26120       # expected = lookup(expected->next)
26121       (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
26122       89/<- %edx 0/r32/eax
26123       #
26124       e9/jump loop/disp32
26125     }
26126 $check-mu-call:check-output-count:
26127     # if (outputs == expected) proceed
26128     39/compare %ecx 2/r32/edx
26129     {
26130       0f 84/jump-if-= break/disp32
26131       # exactly one of the two is null
26132       # if (outputs == 0) error("too many outputs")
26133       {
26134         81 7/subop/compare %ecx 0/imm32
26135         0f 84/jump-if-= break/disp32
26136         (write-buffered *(ebp+0x14) "fn ")
26137         8b/-> *(ebp+0x10) 0/r32/eax
26138         (lookup *eax *(eax+4))  # Function-name Function-name => eax
26139         (write-buffered *(ebp+0x14) %eax)
26140         (write-buffered *(ebp+0x14) ": call ")
26141         (lookup *edi *(edi+4))  # Function-name Function-name => eax
26142         (write-buffered *(ebp+0x14) %eax)
26143         (write-buffered *(ebp+0x14) ": too many outputs\n")
26144         (flush *(ebp+0x14))
26145         (stop *(ebp+0x18) 1)
26146       }
26147       # if (expected == 0) error("too few outputs")
26148       {
26149         81 7/subop/compare %edx 0/imm32
26150         0f 84/jump-if-= break/disp32
26151         (write-buffered *(ebp+0x14) "fn ")
26152         8b/-> *(ebp+0x10) 0/r32/eax
26153         (lookup *eax *(eax+4))  # Function-name Function-name => eax
26154         (write-buffered *(ebp+0x14) %eax)
26155         (write-buffered *(ebp+0x14) ": call ")
26156         (lookup *edi *(edi+4))  # Function-name Function-name => eax
26157         (write-buffered *(ebp+0x14) %eax)
26158         (write-buffered *(ebp+0x14) ": too few outputs\n")
26159         (flush *(ebp+0x14))
26160         (stop *(ebp+0x18) 1)
26161       }
26162     }
26163 $check-mu-call:end:
26164     # . restore registers
26165     5f/pop-to-edi
26166     5e/pop-to-esi
26167     5b/pop-to-ebx
26168     5a/pop-to-edx
26169     59/pop-to-ecx
26170     58/pop-to-eax
26171     # . reclaim locals exclusively on the stack
26172     81 0/subop/add %esp 0x70/imm32
26173     # . epilogue
26174     89/<- %esp 5/r32/ebp
26175     5d/pop-to-ebp
26176     c3/return
26177 
26178 # like type-equal? but takes literals type parameters into account
26179 type-match?:  # def: (addr type-tree), call: (addr type-tree), type-parameters: (addr table (handle array byte) (addr type-tree)) -> result/eax: boolean
26180     # . prologue
26181     55/push-ebp
26182     89/<- %ebp 4/r32/esp
26183     # if (call is literal and def is numberlike) return true
26184     {
26185 $type-match?:check-literal-int:
26186       (is-simple-mu-type? *(ebp+0xc) 0)  # literal => eax
26187       3d/compare-eax-and 0/imm32/false
26188       74/jump-if-= break/disp8
26189       (is-mu-numberlike-output? *(ebp+8))  # => eax
26190       3d/compare-eax-and 0/imm32/false
26191       74/jump-if-= break/disp8
26192       b8/copy-to-eax 1/imm32/true
26193       e9/jump $type-match?:end/disp32
26194     }
26195     # if (call is literal-string and def is string) return true
26196     {
26197 $type-match?:check-literal-string:
26198       (is-simple-mu-type? *(ebp+0xc) 0x10)  # literal-string => eax
26199       3d/compare-eax-and 0/imm32/false
26200       74/jump-if-= break/disp8
26201       (is-mu-string-type? *(ebp+8))  # => eax
26202       3d/compare-eax-and 0/imm32/false
26203       74/jump-if-= break/disp8
26204       b8/copy-to-eax 1/imm32/true
26205       e9/jump $type-match?:end/disp32
26206     }
26207 $type-match?:baseline:
26208     # otherwise fall back
26209     (type-component-match? *(ebp+8) *(ebp+0xc) *(ebp+0x10))  # => eax
26210 $type-match?:end:
26211     # . epilogue
26212     89/<- %esp 5/r32/ebp
26213     5d/pop-to-ebp
26214     c3/return
26215 
26216 type-component-match?:  # def: (addr type-tree), call: (addr type-tree), type-parameters: (addr table (handle array byte) (addr type-tree)) -> result/eax: boolean
26217     # . prologue
26218     55/push-ebp
26219     89/<- %ebp 4/r32/esp
26220     # . save registers
26221     51/push-ecx
26222     52/push-edx
26223     53/push-ebx
26224     # ecx = def
26225     8b/-> *(ebp+8) 1/r32/ecx
26226     # edx = call
26227     8b/-> *(ebp+0xc) 2/r32/edx
26228 $type-component-match?:compare-addr:
26229     # if (def == call) return true
26230     8b/-> %ecx 0/r32/eax  # Var-type
26231     39/compare %edx 0/r32/eax  # Var-type
26232     b8/copy-to-eax 1/imm32/true
26233     0f 84/jump-if-= $type-component-match?:end/disp32
26234     # if (def == 0) return false
26235     b8/copy-to-eax 0/imm32/false
26236     81 7/subop/compare %ecx 0/imm32  # Type-tree-is-atom
26237     0f 84/jump-if-= $type-component-match?:end/disp32
26238     # if (call == 0) return false
26239     81 7/subop/compare %edx 0/imm32  # Type-tree-is-atom
26240     0f 84/jump-if-= $type-component-match?:end/disp32
26241     # if def is a type parameter, just check in type-parameters
26242     {
26243 $type-component-match?:check-type-parameter:
26244       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
26245       74/jump-if-= break/disp8
26246       81 7/subop/compare *(ecx+4) 0xa/imm32/type-parameter  # Type-tree-value
26247       75/jump-if-!= break/disp8
26248 $type-component-match?:type-parameter:
26249       (type-parameter-match? *(ecx+8) *(ecx+0xc)  %edx  *(ebp+0x10))  # => eax
26250       e9/jump $type-component-match?:end/disp32
26251     }
26252     # if def is a list containing just a type parameter, just check in type-parameters
26253     {
26254 $type-component-match?:check-list-type-parameter:
26255       # if def is a list..
26256       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
26257       75/jump-if-!= break/disp8
26258       #   ..that's a singleton
26259       81 7/subop/compare *(ecx+0xc) 0/imm32  # Type-tree-left
26260       75/jump-if-!= break/disp8
26261       #   ..and whose head is a type parameter
26262       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
26263       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
26264       74/jump-if-= break/disp8
26265       81 7/subop/compare *(eax+4) 0xa/imm32/type-parameter  # Type-tree-value
26266       75/jump-if-!= break/disp8
26267 $type-component-match?:list-type-parameter:
26268       (type-parameter-match? *(eax+8) *(eax+0xc)  %edx  *(ebp+0x10))  # => eax
26269       e9/jump $type-component-match?:end/disp32
26270     }
26271 $type-component-match?:compare-atom-state:
26272     # if (def->is-atom? != call->is-atom?) return false
26273     8b/-> *ecx 3/r32/ebx  # Type-tree-is-atom
26274     39/compare *edx 3/r32/ebx  # Type-tree-is-atom
26275     b8/copy-to-eax 0/imm32/false
26276     0f 85/jump-if-!= $type-component-match?:end/disp32
26277     # if def->is-atom? return (def->value == call->value)
26278     {
26279 $type-component-match?:check-atom:
26280       81 7/subop/compare %ebx 0/imm32/false
26281       74/jump-if-= break/disp8
26282 $type-component-match?:is-atom:
26283       8b/-> *(ecx+4) 0/r32/eax  # Type-tree-value
26284       39/compare *(edx+4) 0/r32/eax  # Type-tree-value
26285       0f 94/set-if-= %al
26286       81 4/subop/and %eax 0xff/imm32
26287       e9/jump $type-component-match?:end/disp32
26288     }
26289 $type-component-match?:check-left:
26290     # if (!type-component-match?(def->left, call->left)) return false
26291     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
26292     89/<- %ebx 0/r32/eax
26293     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
26294     (type-component-match? %ebx %eax *(ebp+0x10))  # => eax
26295     3d/compare-eax-and 0/imm32/false
26296     74/jump-if-= $type-component-match?:end/disp8
26297 $type-component-match?:check-right:
26298     # return type-component-match?(def->right, call->right)
26299     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
26300     89/<- %ebx 0/r32/eax
26301     (lookup *(edx+0xc) *(edx+0x10))  # Type-tree-right Type-tree-right => eax
26302     (type-component-match? %ebx %eax *(ebp+0x10))  # => eax
26303 $type-component-match?:end:
26304     # . restore registers
26305     5b/pop-to-ebx
26306     5a/pop-to-edx
26307     59/pop-to-ecx
26308     # . epilogue
26309     89/<- %esp 5/r32/ebp
26310     5d/pop-to-ebp
26311     c3/return
26312 
26313 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
26314     # . prologue
26315     55/push-ebp
26316     89/<- %ebp 4/r32/esp
26317     # . save registers
26318     51/push-ecx
26319     #
26320     (get-or-insert-handle *(ebp+0x14)  *(ebp+8) *(ebp+0xc)  0xc)  # => eax
26321     # if parameter wasn't saved, save it
26322     {
26323       81 7/subop/compare *eax 0/imm32
26324       75/jump-if-!= break/disp8
26325       8b/-> *(ebp+0x10) 1/r32/ecx
26326       89/<- *eax 1/r32/ecx
26327     }
26328     #
26329     (type-equal? *(ebp+0x10) *eax)  # => eax
26330 $type-parameter-match?:end:
26331     # . restore registers
26332     59/pop-to-ecx
26333     # . epilogue
26334     89/<- %esp 5/r32/ebp
26335     5d/pop-to-ebp
26336     c3/return
26337 
26338 size-of:  # v: (addr var) -> result/eax: int
26339     # . prologue
26340     55/push-ebp
26341     89/<- %ebp 4/r32/esp
26342     # . save registers
26343     51/push-ecx
26344     # var t/ecx: (addr type-tree) = lookup(v->type)
26345     8b/-> *(ebp+8) 1/r32/ecx
26346 #?     (write-buffered Stderr "size-of ")
26347 #?     (write-int32-hex-buffered Stderr %ecx)
26348 #?     (write-buffered Stderr Newline)
26349 #?     (write-buffered Stderr "type allocid: ")
26350 #?     (write-int32-hex-buffered Stderr *(ecx+8))
26351 #?     (write-buffered Stderr Newline)
26352 #?     (flush Stderr)
26353     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
26354     89/<- %ecx 0/r32/eax
26355     # if is-mu-array?(t) return size-of-array(t)
26356     {
26357       (is-mu-array? %ecx)  # => eax
26358       3d/compare-eax-and 0/imm32/false
26359       74/jump-if-= break/disp8
26360       (size-of-array %ecx)  # => eax
26361       eb/jump $size-of:end/disp8
26362     }
26363     # if is-mu-stream?(t) return size-of-stream(t)
26364     {
26365       (is-mu-stream? %ecx)  # => eax
26366       3d/compare-eax-and 0/imm32/false
26367       74/jump-if-= break/disp8
26368       (size-of-stream %ecx)  # => eax
26369       eb/jump $size-of:end/disp8
26370     }
26371     # if (!t->is-atom?) t = lookup(t->left)
26372     {
26373       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
26374       75/jump-if-!= break/disp8
26375       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
26376       89/<- %ecx 0/r32/eax
26377     }
26378     # TODO: assert t->is-atom?
26379     (size-of-type-id *(ecx+4))  # Type-tree-value => eax
26380 $size-of:end:
26381     # . restore registers
26382     59/pop-to-ecx
26383     # . epilogue
26384     89/<- %esp 5/r32/ebp
26385     5d/pop-to-ebp
26386     c3/return
26387 
26388 size-of-deref:  # v: (addr var) -> result/eax: int
26389     # . prologue
26390     55/push-ebp
26391     89/<- %ebp 4/r32/esp
26392     # . save registers
26393     51/push-ecx
26394     # var t/ecx: (addr type-tree) = lookup(v->type)
26395     8b/-> *(ebp+8) 1/r32/ecx
26396     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
26397     89/<- %ecx 0/r32/eax
26398     # TODO: assert(t is an addr)
26399     # t = lookup(t->right)
26400     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
26401     89/<- %ecx 0/r32/eax
26402     # if is-mu-array?(t) return size-of-array(t)
26403     {
26404       (is-mu-array? %ecx)  # => eax
26405       3d/compare-eax-and 0/imm32/false
26406       74/jump-if-= break/disp8
26407       (size-of-array %ecx)  # => eax
26408       eb/jump $size-of-deref:end/disp8
26409     }
26410     # if is-mu-stream?(t) return size-of-stream(t)
26411     {
26412       (is-mu-stream? %ecx)  # => eax
26413       3d/compare-eax-and 0/imm32/false
26414       74/jump-if-= break/disp8
26415       (size-of-stream %ecx)  # => eax
26416       eb/jump $size-of-deref:end/disp8
26417     }
26418     # if (!t->is-atom?) t = lookup(t->left)
26419     {
26420       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
26421       75/jump-if-!= break/disp8
26422       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
26423       89/<- %ecx 0/r32/eax
26424     }
26425     # TODO: assert t->is-atom?
26426     (size-of-type-id *(ecx+4))  # Type-tree-value => eax
26427 $size-of-deref:end:
26428     # . restore registers
26429     59/pop-to-ecx
26430     # . epilogue
26431     89/<- %esp 5/r32/ebp
26432     5d/pop-to-ebp
26433     c3/return
26434 
26435 is-mu-array?:  # t: (addr type-tree) -> result/eax: boolean
26436     # . prologue
26437     55/push-ebp
26438     89/<- %ebp 4/r32/esp
26439     # . save registers
26440     51/push-ecx
26441     # ecx = t
26442     8b/-> *(ebp+8) 1/r32/ecx
26443     # if t->is-atom?, return false
26444     81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
26445     75/jump-if-!= $is-mu-array?:return-false/disp8
26446     # if !t->left->is-atom?, return false
26447     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
26448     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
26449     74/jump-if-= $is-mu-array?:return-false/disp8
26450     # return t->left->value == array
26451     81 7/subop/compare *(eax+4) 3/imm32/array-type-id  # Type-tree-value
26452     0f 94/set-if-= %al
26453     81 4/subop/and %eax 0xff/imm32
26454     eb/jump $is-mu-array?:end/disp8
26455 $is-mu-array?:return-false:
26456     b8/copy-to-eax 0/imm32/false
26457 $is-mu-array?:end:
26458     # . restore registers
26459     59/pop-to-ecx
26460     # . epilogue
26461     89/<- %esp 5/r32/ebp
26462     5d/pop-to-ebp
26463     c3/return
26464 
26465 # size of a statically allocated array where the size is part of the type expression
26466 size-of-array:  # a: (addr type-tree) -> result/eax: int
26467     # . prologue
26468     55/push-ebp
26469     89/<- %ebp 4/r32/esp
26470     # . save registers
26471     51/push-ecx
26472     52/push-edx
26473     #
26474     8b/-> *(ebp+8) 1/r32/ecx
26475     # TODO: assert that a->left is 'array'
26476     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
26477     89/<- %ecx 0/r32/eax
26478     # var elem-type/edx: type-id = a->right->left->value
26479     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
26480     8b/-> *(eax+4) 2/r32/edx  # Type-tree-value
26481     # TODO: assert that a->right->right->left->value == size
26482     # var array-size/ecx: int = a->right->right->left->value-size
26483     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
26484     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
26485     8b/-> *(eax+8) 1/r32/ecx  # Type-tree-value-size
26486     # return 4 + array-size * size-of(elem-type)
26487     (size-of-type-id-as-array-element %edx)  # => eax
26488     f7 4/subop/multiply-into-edx-eax %ecx
26489     05/add-to-eax 4/imm32  # for array size
26490     # TODO: check edx for overflow
26491 $size-of-array:end:
26492     # . restore registers
26493     5a/pop-to-edx
26494     59/pop-to-ecx
26495     # . epilogue
26496     89/<- %esp 5/r32/ebp
26497     5d/pop-to-ebp
26498     c3/return
26499 
26500 is-mu-stream?:  # t: (addr type-tree) -> result/eax: boolean
26501     # . prologue
26502     55/push-ebp
26503     89/<- %ebp 4/r32/esp
26504     # . save registers
26505     51/push-ecx
26506     # ecx = t
26507     8b/-> *(ebp+8) 1/r32/ecx
26508     # if t->is-atom?, return false
26509     81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
26510     75/jump-if-!= $is-mu-stream?:return-false/disp8
26511     # if !t->left->is-atom?, return false
26512     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
26513     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
26514     74/jump-if-= $is-mu-stream?:return-false/disp8
26515     # return t->left->value == stream
26516     81 7/subop/compare *(eax+4) 0xb/imm32/stream-type-id  # Type-tree-value
26517     0f 94/set-if-= %al
26518     81 4/subop/and %eax 0xff/imm32
26519     eb/jump $is-mu-stream?:end/disp8
26520 $is-mu-stream?:return-false:
26521     b8/copy-to-eax 0/imm32/false
26522 $is-mu-stream?:end:
26523     # . restore registers
26524     59/pop-to-ecx
26525     # . epilogue
26526     89/<- %esp 5/r32/ebp
26527     5d/pop-to-ebp
26528     c3/return
26529 
26530 # size of a statically allocated stream where the size is part of the type expression
26531 size-of-stream:  # a: (addr type-tree) -> result/eax: int
26532     # . prologue
26533     55/push-ebp
26534     89/<- %ebp 4/r32/esp
26535     #
26536     (size-of-array *(ebp+8))  # assumes we ignore the actual type name 'array' in the type
26537     05/add-to-eax 8/imm32  # for read/write pointers
26538 $size-of-stream:end:
26539     # . epilogue
26540     89/<- %esp 5/r32/ebp
26541     5d/pop-to-ebp
26542     c3/return
26543 
26544 size-of-type-id:  # t: type-id -> result/eax: int
26545     # . prologue
26546     55/push-ebp
26547     89/<- %ebp 4/r32/esp
26548     # . save registers
26549     51/push-ecx
26550     # var out/ecx: (handle typeinfo)
26551     68/push 0/imm32
26552     68/push 0/imm32
26553     89/<- %ecx 4/r32/esp
26554     # eax = t
26555     8b/-> *(ebp+8) 0/r32/eax
26556     # if t is a literal, return 0
26557     3d/compare-eax-and 0/imm32
26558     0f 84/jump-if-= $size-of-type-id:end/disp32  # eax changes type from type-id to int
26559     # if t is a byte, return 4 (because we don't really support non-multiples of 4)
26560     3d/compare-eax-and 8/imm32/byte
26561     {
26562       75/jump-if-!= break/disp8
26563       b8/copy-to-eax 4/imm32
26564       eb/jump $size-of-type-id:end/disp8
26565     }
26566     # if t is a handle, return 8
26567     3d/compare-eax-and 4/imm32/handle
26568     {
26569       75/jump-if-!= break/disp8
26570       b8/copy-to-eax 8/imm32
26571       eb/jump $size-of-type-id:end/disp8  # eax changes type from type-id to int
26572     }
26573     # if t is a slice, return 8
26574     3d/compare-eax-and 0xc/imm32/slice
26575     {
26576       75/jump-if-!= break/disp8
26577       b8/copy-to-eax 8/imm32
26578       eb/jump $size-of-type-id:end/disp8  # eax changes type from type-id to int
26579     }
26580     # if t is a user-defined type, return its size
26581     # TODO: support non-atom type
26582     (find-typeinfo %eax %ecx)
26583     {
26584       81 7/subop/compare *ecx 0/imm32
26585       74/jump-if-= break/disp8
26586 $size-of-type-id:user-defined:
26587       (lookup *ecx *(ecx+4))  # => eax
26588       8b/-> *(eax+0xc) 0/r32/eax  # Typeinfo-total-size-in-bytes
26589       eb/jump $size-of-type-id:end/disp8
26590     }
26591     # otherwise return the word size
26592     b8/copy-to-eax 4/imm32
26593 $size-of-type-id:end:
26594     # . reclaim locals
26595     81 0/subop/add %esp 8/imm32
26596     # . restore registers
26597     59/pop-to-ecx
26598     # . epilogue
26599     89/<- %esp 5/r32/ebp
26600     5d/pop-to-ebp
26601     c3/return
26602 
26603 # Minor violation of our type system since it returns an addr. But we could
26604 # replace it with a handle some time.
26605 # Returns null if t is an atom.
26606 type-tail:  # t: (addr type-tree) -> out/eax: (addr type-tree)
26607     # . prologue
26608     55/push-ebp
26609     89/<- %ebp 4/r32/esp
26610     # . save registers
26611     51/push-ecx
26612     # eax = 0
26613     b8/copy-to-eax 0/imm32
26614     # ecx = t
26615     8b/-> *(ebp+8) 1/r32/ecx
26616 $type-tail:check-atom:
26617     # if t->is-atom? return 0
26618     81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
26619     0f 85/jump-if-!= $type-tail:end/disp32
26620     # var tail = t->right
26621     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
26622     89/<- %ecx 0/r32/eax
26623 $type-tail:check-singleton:
26624     # if (tail->right == 0) return tail->left
26625     {
26626       81 7/subop/compare *(ecx+0xc) 0/imm32  # Type-tree-right
26627       75/jump-if-!= break/disp8
26628       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
26629       e9/jump $type-tail:end/disp32
26630     }
26631     # if tail->right->left is an array-capacity, return tail->left
26632     {
26633 $type-tail:check-array-capacity:
26634       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
26635       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
26636       75/jump-if-!= break/disp8
26637 $type-tail:check-array-capacity-1:
26638       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
26639       3d/compare-eax-and 0/imm32
26640       74/jump-if-= break/disp8
26641 $type-tail:check-array-capacity-2:
26642       (is-simple-mu-type? %eax 9)  # array-capacity => eax
26643       3d/compare-eax-and 0/imm32/false
26644       74/jump-if-= break/disp8
26645 $type-tail:array-capacity:
26646       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
26647       eb/jump $type-tail:end/disp8
26648     }
26649 $type-tail:check-compound-left:
26650     # if !tail->left->is-atom? return tail->left
26651     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
26652     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
26653     74/jump-if-= $type-tail:end/disp8
26654 $type-tail:return-tail:
26655     # return tail
26656     89/<- %eax 1/r32/ecx
26657 $type-tail:end:
26658     # . restore registers
26659     59/pop-to-ecx
26660     # . epilogue
26661     89/<- %esp 5/r32/ebp
26662     5d/pop-to-ebp
26663     c3/return
26664 
26665 type-equal?:  # a: (addr type-tree), b: (addr type-tree) -> result/eax: boolean
26666     # . prologue
26667     55/push-ebp
26668     89/<- %ebp 4/r32/esp
26669     # . save registers
26670     51/push-ecx
26671     52/push-edx
26672     53/push-ebx
26673     # ecx = a
26674     8b/-> *(ebp+8) 1/r32/ecx
26675     # edx = b
26676     8b/-> *(ebp+0xc) 2/r32/edx
26677 $type-equal?:compare-addr:
26678     # if (a == b) return true
26679     8b/-> %ecx 0/r32/eax  # Var-type
26680     39/compare %edx 0/r32/eax  # Var-type
26681     b8/copy-to-eax 1/imm32/true
26682     0f 84/jump-if-= $type-equal?:end/disp32
26683 $type-equal?:compare-null-a:
26684     # if (a == 0) return false
26685     b8/copy-to-eax 0/imm32/false
26686     81 7/subop/compare %ecx 0/imm32
26687     0f 84/jump-if-= $type-equal?:end/disp32
26688 $type-equal?:compare-null-b:
26689     # if (b == 0) return false
26690     81 7/subop/compare %edx 0/imm32
26691     0f 84/jump-if-= $type-equal?:end/disp32
26692 $type-equal?:compare-atom-state:
26693     # if (a->is-atom? != b->is-atom?) return false
26694     8b/-> *ecx 3/r32/ebx  # Type-tree-is-atom
26695     39/compare *edx 3/r32/ebx  # Type-tree-is-atom
26696     b8/copy-to-eax 0/imm32/false
26697     0f 85/jump-if-!= $type-equal?:end/disp32
26698     # if a->is-atom? return (a->value == b->value)
26699     {
26700 $type-equal?:check-atom:
26701       81 7/subop/compare %ebx 0/imm32/false
26702       74/jump-if-= break/disp8
26703 $type-equal?:is-atom:
26704       8b/-> *(ecx+4) 0/r32/eax  # Type-tree-value
26705       39/compare *(edx+4) 0/r32/eax  # Type-tree-value
26706       0f 94/set-if-= %al
26707       81 4/subop/and %eax 0xff/imm32
26708       e9/jump $type-equal?:end/disp32
26709     }
26710 $type-equal?:check-left:
26711     # if (!type-equal?(a->left, b->left)) return false
26712     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
26713     89/<- %ebx 0/r32/eax
26714     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
26715     (type-equal? %eax %ebx)  # => eax
26716     3d/compare-eax-and 0/imm32/false
26717     74/jump-if-= $type-equal?:end/disp8
26718 $type-equal?:check-right:
26719     # return type-equal?(a->right, b->right)
26720     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
26721     89/<- %ebx 0/r32/eax
26722     (lookup *(edx+0xc) *(edx+0x10))  # Type-tree-right Type-tree-right => eax
26723     (type-equal? %eax %ebx)  # => eax
26724 $type-equal?:end:
26725     # . restore registers
26726     5b/pop-to-ebx
26727     5a/pop-to-edx
26728     59/pop-to-ecx
26729     # . epilogue
26730     89/<- %esp 5/r32/ebp
26731     5d/pop-to-ebp
26732     c3/return
26733 
26734 #######################################################
26735 # Code-generation
26736 #######################################################
26737 
26738 == data
26739 
26740 # Global state added to each var record when performing code-generation.
26741 Curr-local-stack-offset:  # (addr int)
26742     0/imm32
26743 
26744 == code
26745 
26746 # We may not need to pass err/ed everywhere here. I think they're relics of Mu
26747 # getting type checks later in life.
26748 # But we do need them for runtime checks, particularly array index bounds checks.
26749 # So perhaps it's not worth taking them out. They're a safety net.
26750 
26751 emit-subx:  # out: (addr buffered-file), err: (addr buffered-file), ed: (addr exit-descriptor)
26752     # . prologue
26753     55/push-ebp
26754     89/<- %ebp 4/r32/esp
26755     # . save registers
26756     50/push-eax
26757     # var curr/eax: (addr function) = *Program->functions
26758     (lookup *_Program-functions *_Program-functions->payload)  # => eax
26759     {
26760       # if (curr == null) break
26761       3d/compare-eax-and 0/imm32
26762       0f 84/jump-if-= break/disp32
26763       (emit-subx-function *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10))
26764       # curr = lookup(curr->next)
26765       (lookup *(eax+0x20) *(eax+0x24))  # Function-next Function-next => eax
26766       e9/jump loop/disp32
26767     }
26768 $emit-subx:end:
26769     # . restore registers
26770     58/pop-to-eax
26771     # . epilogue
26772     89/<- %esp 5/r32/ebp
26773     5d/pop-to-ebp
26774     c3/return
26775 
26776 emit-subx-function:  # out: (addr buffered-file), f: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
26777     # . prologue
26778     55/push-ebp
26779     89/<- %ebp 4/r32/esp
26780     # some preprocessing
26781     (populate-mu-type-offsets-in-inouts *(ebp+0xc))
26782     # . save registers
26783     50/push-eax
26784     51/push-ecx
26785     52/push-edx
26786     # initialize some global state
26787     c7 0/subop/copy *Curr-block-depth 1/imm32  # Important: keep this in sync with the parse phase
26788     c7 0/subop/copy *Curr-local-stack-offset 0/imm32
26789     # ecx = f
26790     8b/-> *(ebp+0xc) 1/r32/ecx
26791     # var vars/edx: (stack (addr var) 256)
26792     81 5/subop/subtract %esp 0xc00/imm32
26793     68/push 0xc00/imm32/size
26794     68/push 0/imm32/top
26795     89/<- %edx 4/r32/esp
26796     # var name/eax: (addr array byte) = lookup(f->name)
26797     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
26798     #
26799     (write-buffered *(ebp+8) %eax)
26800     (write-buffered *(ebp+8) ":\n")
26801     (emit-subx-prologue *(ebp+8))
26802     # var body/eax: (addr block) = lookup(f->body)
26803     (lookup *(ecx+0x18) *(ecx+0x1c))  # Function-body Function-body => eax
26804     #
26805     (emit-subx-block *(ebp+8) %eax %edx *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
26806     (emit-subx-epilogue *(ebp+8))
26807     # TODO: validate that *Curr-block-depth and *Curr-local-stack-offset have
26808     # been cleaned up
26809 $emit-subx-function:end:
26810     # . reclaim locals
26811     81 0/subop/add %esp 0xc08/imm32
26812     # . restore registers
26813     5a/pop-to-edx
26814     59/pop-to-ecx
26815     58/pop-to-eax
26816     # . epilogue
26817     89/<- %esp 5/r32/ebp
26818     5d/pop-to-ebp
26819     c3/return
26820 
26821 populate-mu-type-offsets-in-inouts:  # f: (addr function)
26822     # . prologue
26823     55/push-ebp
26824     89/<- %ebp 4/r32/esp
26825     # . save registers
26826     50/push-eax
26827     51/push-ecx
26828     52/push-edx
26829     53/push-ebx
26830     57/push-edi
26831     # var next-offset/edx: int = 8
26832     ba/copy-to-edx 8/imm32
26833     # var curr/ecx: (addr list var) = lookup(f->inouts)
26834     8b/-> *(ebp+8) 1/r32/ecx
26835     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
26836     89/<- %ecx 0/r32/eax
26837     {
26838 $populate-mu-type-offsets-in-inouts:loop:
26839       81 7/subop/compare %ecx 0/imm32
26840       74/jump-if-= break/disp8
26841       # var v/ebx: (addr var) = lookup(curr->value)
26842       (lookup *ecx *(ecx+4))  # List-value List-value => eax
26843       89/<- %ebx 0/r32/eax
26844 #?       (lookup *ebx *(ebx+4))
26845 #?       (write-buffered Stderr "setting offset of fn inout ")
26846 #?       (write-buffered Stderr %eax)
26847 #?       (write-buffered Stderr "@")
26848 #?       (write-int32-hex-buffered Stderr %ebx)
26849 #?       (write-buffered Stderr " to ")
26850 #?       (write-int32-hex-buffered Stderr %edx)
26851 #?       (write-buffered Stderr Newline)
26852 #?       (flush Stderr)
26853       # v->offset = next-offset
26854       89/<- *(ebx+0x14) 2/r32/edx  # Var-offset
26855       # next-offset += size-of(v)
26856       (size-of %ebx)  # => eax
26857       01/add-to %edx 0/r32/eax
26858       # curr = lookup(curr->next)
26859       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
26860       89/<- %ecx 0/r32/eax
26861       #
26862       eb/jump loop/disp8
26863     }
26864 $populate-mu-type-offsets-in-inouts:end:
26865     # . restore registers
26866     5f/pop-to-edi
26867     5b/pop-to-ebx
26868     5a/pop-to-edx
26869     59/pop-to-ecx
26870     58/pop-to-eax
26871     # . epilogue
26872     89/<- %esp 5/r32/ebp
26873     5d/pop-to-ebp
26874     c3/return
26875 
26876 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)
26877     # . prologue
26878     55/push-ebp
26879     89/<- %ebp 4/r32/esp
26880     # . save registers
26881     50/push-eax
26882     51/push-ecx
26883     53/push-ebx
26884     56/push-esi
26885     # esi = stmts
26886     8b/-> *(ebp+0xc) 6/r32/esi
26887     #
26888     {
26889 $emit-subx-stmt-list:loop:
26890       81 7/subop/compare %esi 0/imm32
26891       0f 84/jump-if-= break/disp32
26892       # var curr-stmt/ecx: (addr stmt) = lookup(stmts->value)
26893       (lookup *esi *(esi+4))  # List-value List-value => eax
26894       89/<- %ecx 0/r32/eax
26895       {
26896 $emit-subx-stmt-list:check-for-block:
26897         81 7/subop/compare *ecx 0/imm32/block  # Stmt-tag
26898         75/jump-if-!= break/disp8
26899 $emit-subx-stmt-list:block:
26900         (emit-subx-block *(ebp+8) %ecx *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
26901       }
26902       {
26903 $emit-subx-stmt-list:check-for-stmt:
26904         81 7/subop/compare *ecx 1/imm32/stmt1  # Stmt-tag
26905         0f 85/jump-if-!= break/disp32
26906 $emit-subx-stmt-list:stmt1:
26907         {
26908           (is-mu-branch? %ecx)  # => eax
26909           3d/compare-eax-and 0/imm32/false
26910           0f 84/jump-if-= break/disp32
26911 $emit-subx-stmt-list:branch-stmt:
26912 +-- 25 lines: # unconditional return ----------------------------------------------------------------------------------------------------------------------------------------------------
26937 +-- 27 lines: # unconditional loops -----------------------------------------------------------------------------------------------------------------------------------------------------
26964 +-- 16 lines: # unconditional breaks ----------------------------------------------------------------------------------------------------------------------------------------------------
26980 +-- 38 lines: # simple conditional branches without a target ----------------------------------------------------------------------------------------------------------------------------
27018 +-- 19 lines: # conditional branches with an explicit target ----------------------------------------------------------------------------------------------------------------------------
27037         }
27038 $emit-subx-stmt-list:1-to-1:
27039         (emit-subx-stmt *(ebp+8) %ecx Primitives *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
27040         e9/jump $emit-subx-stmt-list:continue/disp32
27041       }
27042       {
27043 $emit-subx-stmt-list:check-for-var-def:
27044         81 7/subop/compare *ecx 2/imm32/var-def  # Stmt-tag
27045         75/jump-if-!= break/disp8
27046 $emit-subx-stmt-list:var-def:
27047         (emit-subx-var-def *(ebp+8) %ecx)
27048         (push *(ebp+0x10) *(ecx+4))  # Vardef-var
27049         (push *(ebp+0x10) *(ecx+8))  # Vardef-var
27050         (push *(ebp+0x10) 0)  # Live-var-register-spilled = 0 for vars on the stack
27051         #
27052         eb/jump $emit-subx-stmt-list:continue/disp8
27053       }
27054       {
27055 $emit-subx-stmt-list:check-for-reg-var-def:
27056         81 7/subop/compare *ecx 3/imm32/reg-var-def  # Stmt-tag
27057         0f 85/jump-if-!= break/disp32
27058 $emit-subx-stmt-list:reg-var-def:
27059         # TODO: ensure that there's exactly one output
27060         (push-output-and-maybe-emit-spill *(ebp+8) %ecx *(ebp+0x10) %esi *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
27061         # emit the instruction as usual
27062         (emit-subx-stmt *(ebp+8) %ecx Primitives *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
27063         #
27064         eb/jump $emit-subx-stmt-list:continue/disp8
27065       }
27066 $emit-subx-stmt-list:continue:
27067       # TODO: raise an error on unrecognized Stmt-tag
27068       (lookup *(esi+8) *(esi+0xc))  # List-next List-next => eax
27069       89/<- %esi 0/r32/eax
27070       e9/jump loop/disp32
27071     }
27072 $emit-subx-stmt-list:emit-cleanup:
27073     (emit-cleanup-code-until-depth *(ebp+8) *(ebp+0x10) *Curr-block-depth)
27074 $emit-subx-stmt-list:clean-up:
27075     (clean-up-stack-offset-state *(ebp+0x10) *Curr-block-depth)
27076     (clean-up-blocks *(ebp+0x10) *Curr-block-depth *(ebp+0x14))
27077 $emit-subx-stmt-list:end:
27078     # . restore registers
27079     5e/pop-to-esi
27080     5b/pop-to-ebx
27081     59/pop-to-ecx
27082     58/pop-to-eax
27083     # . epilogue
27084     89/<- %esp 5/r32/ebp
27085     5d/pop-to-ebp
27086     c3/return
27087 
27088 # 'later-stmts' includes 'stmt', but will behave the same even without it; reg-var-def stmts are guaranteed not to write to function outputs.
27089 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)
27090     # . prologue
27091     55/push-ebp
27092     89/<- %ebp 4/r32/esp
27093     # . save registers
27094     50/push-eax
27095     51/push-ecx
27096     52/push-edx
27097     # ecx = stmt
27098     8b/-> *(ebp+0xc) 1/r32/ecx
27099     # var sv/eax: (addr stmt-var) = lookup(curr-stmt->outputs)
27100     (lookup *(ecx+0x14) *(ecx+0x18))  # Regvardef-outputs Regvardef-outputs => eax
27101     # TODO: assert !sv->is-deref?
27102     # var v/ecx: (addr var) = lookup(sv->value)
27103     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
27104     89/<- %ecx 0/r32/eax
27105     # v->block-depth = *Curr-block-depth
27106     8b/-> *Curr-block-depth 0/r32/eax
27107     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
27108 #?     (write-buffered Stderr "var ")
27109 #?     (lookup *ecx *(ecx+4))
27110 #?     (write-buffered Stderr %eax)
27111 #?     (write-buffered Stderr " at depth ")
27112 #?     (write-int32-hex-buffered Stderr *(ecx+0x10))
27113 #?     (write-buffered Stderr Newline)
27114 #?     (flush Stderr)
27115     # ensure that v is in a register
27116     81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
27117     0f 84/jump-if-= $push-output-and-maybe-emit-spill:abort/disp32
27118     # var emit-spill?/edx: boolean = not-yet-spilled-this-block? && will-not-write-some-register?(fn)
27119     (not-yet-spilled-this-block? %ecx *(ebp+0x10))  # => eax
27120     89/<- %edx 0/r32/eax
27121     3d/compare-eax-and 0/imm32/false
27122     0f 84/jump-if-= $push-output-and-maybe-emit-spill:push/disp32
27123     (will-not-write-some-register? %ecx *(ebp+0x14) *(ebp+0x18))  # => eax
27124     89/<- %edx 0/r32/eax
27125     # check emit-spill?
27126     3d/compare-eax-and 0/imm32/false
27127     0f 84/jump-if-= $push-output-and-maybe-emit-spill:push/disp32
27128     # TODO: assert(size-of(output) == 4)
27129     # *Curr-local-stack-offset -= 4
27130     81 5/subop/subtract *Curr-local-stack-offset 4/imm32
27131     # emit spill
27132     (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
27133     (emit-push-register *(ebp+8) %eax)
27134 $push-output-and-maybe-emit-spill:push:
27135     8b/-> *(ebp+0xc) 1/r32/ecx
27136     (lookup *(ecx+0x14) *(ecx+0x18))  # Regvardef-outputs Regvardef-outputs => eax
27137     # push(vars, {sv->value, emit-spill?})
27138     (push *(ebp+0x10) *eax)  # Stmt-var-value
27139     (push *(ebp+0x10) *(eax+4))  # Stmt-var-value
27140     (push *(ebp+0x10) %edx)
27141 $push-output-and-maybe-emit-spill:end:
27142     # . restore registers
27143     5a/pop-to-edx
27144     59/pop-to-ecx
27145     58/pop-to-eax
27146     # . epilogue
27147     89/<- %esp 5/r32/ebp
27148     5d/pop-to-ebp
27149     c3/return
27150 
27151 $push-output-and-maybe-emit-spill:abort:
27152     # error("var '" var->name "' initialized from an instruction must live in a register\n")
27153     (write-buffered *(ebp+0x1c) "var '")
27154     (write-buffered *(ebp+0x1c) *eax)  # Var-name
27155     (write-buffered *(ebp+0x1c) "' initialized from an instruction must live in a register\n")
27156     (flush *(ebp+0x1c))
27157     (stop *(ebp+0x20) 1)
27158     # never gets here
27159 
27160 emit-subx-cleanup-and-unconditional-nonlocal-branch:  # out: (addr buffered-file), stmt: (addr stmt1), vars: (addr stack live-var)
27161     # . prologue
27162     55/push-ebp
27163     89/<- %ebp 4/r32/esp
27164     # . save registers
27165     50/push-eax
27166     51/push-ecx
27167     # ecx = stmt
27168     8b/-> *(ebp+0xc) 1/r32/ecx
27169     # var target/eax: (addr array byte) = curr-stmt->inouts->value->name
27170     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
27171     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
27172     (lookup *eax *(eax+4))  # Var-name Var-name => eax
27173     # clean up until target block
27174     (emit-cleanup-code-until-target *(ebp+8) *(ebp+0x10) %eax)
27175     # emit jump to target block
27176     (emit-indent *(ebp+8) *Curr-block-depth)
27177     (write-buffered *(ebp+8) "e9/jump ")
27178     (write-buffered *(ebp+8) %eax)
27179     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
27180     (string-starts-with? %eax "break")
27181     3d/compare-eax-and 0/imm32/false
27182     {
27183       74/jump-if-= break/disp8
27184       (write-buffered *(ebp+8) ":break/disp32\n")
27185       eb/jump $emit-subx-cleanup-and-unconditional-nonlocal-branch:end/disp8
27186     }
27187     (write-buffered *(ebp+8) ":loop/disp32\n")
27188 $emit-subx-cleanup-and-unconditional-nonlocal-branch:end:
27189     # . restore registers
27190     59/pop-to-ecx
27191     58/pop-to-eax
27192     # . epilogue
27193     89/<- %esp 5/r32/ebp
27194     5d/pop-to-ebp
27195     c3/return
27196 
27197 emit-outputs:  # out: (addr buffered-file), return-stmt: (addr stmt1), fn: (addr function)
27198     # . prologue
27199     55/push-ebp
27200     89/<- %ebp 4/r32/esp
27201     # . save registers
27202     50/push-eax
27203     51/push-ecx
27204     56/push-esi
27205     57/push-edi
27206     # var curr-inout/esi: (addr stmt-var) = return-stmt->inouts
27207     8b/-> *(ebp+0xc) 0/r32/eax
27208     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
27209     89/<- %esi 0/r32/eax
27210     # var curr-output/edi: (addr list var) = fn->outputs
27211     8b/-> *(ebp+0x10) 0/r32/eax
27212     (lookup *(eax+0x10) *(eax+0x14))  # Function-outputs Function-outputs => eax
27213     89/<- %edi 0/r32/eax
27214     {
27215 $emit-outputs:loop:
27216       81 7/subop/compare %esi 0/imm32
27217       0f 84/jump-if-= break/disp32
27218       # emit copy to output register
27219       # var curr-output-register/ecx: (addr array byte) = curr-output->value->register
27220       (lookup *edi *(edi+4))  # List-value List-value => eax
27221       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
27222       89/<- %ecx 0/r32/eax
27223       # if curr-output-register starts with "x", emit a floating-point copy
27224       8a/copy-byte *(ecx+4) 0/r32/AL
27225       81 4/subop/and %eax 0xff/imm32
27226       3d/compare-eax-and 0x78/imm32/x
27227       {
27228         75/jump-if-!= break/disp8
27229         (emit-float-output *(ebp+8) %esi %ecx)
27230         eb/jump $emit-outputs:continue/disp8
27231       }
27232       # otherwise emit an int copy
27233       (emit-int-output *(ebp+8) %esi %ecx)
27234 $emit-outputs:continue:
27235       # curr-inout = curr-inout->next
27236       (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
27237       89/<- %esi 0/r32/eax
27238       # curr-output = curr-output->next
27239       (lookup *(edi+8) *(edi+0xc))  # List-next List-next => eax
27240       89/<- %edi 0/r32/eax
27241       #
27242       e9/jump loop/disp32
27243     }
27244 $emit-outputs:end:
27245     # . restore registers
27246     5f/pop-to-edi
27247     5e/pop-to-esi
27248     59/pop-to-ecx
27249     58/pop-to-eax
27250     # . epilogue
27251     89/<- %esp 5/r32/ebp
27252     5d/pop-to-ebp
27253     c3/return
27254 
27255 emit-int-output:  # out: (addr buffered-file), return-var: (addr stmt-var), dest-reg: (addr array byte)
27256     # . prologue
27257     55/push-ebp
27258     89/<- %ebp 4/r32/esp
27259     # . save registers
27260     50/push-eax
27261     51/push-ecx
27262     # ecx = return-var->value
27263     8b/-> *(ebp+0xc) 0/r32/eax
27264     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
27265     89/<- %ecx 0/r32/eax
27266     # if curr-var is a literal, emit copy of a literal to the output
27267     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
27268     (is-simple-mu-type? %eax 0)  # literal => eax
27269     {
27270       3d/compare-eax-and 0/imm32/false
27271       0f 84/jump-if-= break/disp32
27272       (emit-indent *(ebp+8) *Curr-block-depth)
27273       (write-buffered *(ebp+8) "c7 0/subop/copy %")
27274       (write-buffered *(ebp+8) *(ebp+0x10))
27275       (write-buffered *(ebp+8) " ")
27276       (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
27277       (write-buffered *(ebp+8) %eax)
27278       (write-buffered *(ebp+8) "/imm32\n")
27279       e9/jump $emit-int-output:end/disp32
27280     }
27281     # otherwise emit an integer copy
27282     (emit-indent *(ebp+8) *Curr-block-depth)
27283     (write-buffered *(ebp+8) "8b/->")
27284     (emit-subx-var-as-rm32 *(ebp+8) *(ebp+0xc))
27285     (write-buffered *(ebp+8) " ")
27286     (get Mu-registers *(ebp+0x10) 0xc "Mu-registers")  # => eax
27287     (write-int32-hex-buffered *(ebp+8) *eax)
27288     (write-buffered *(ebp+8) "/r32\n")
27289 $emit-int-output:end:
27290     # . restore registers
27291     59/pop-to-ecx
27292     58/pop-to-eax
27293     # . epilogue
27294     89/<- %esp 5/r32/ebp
27295     5d/pop-to-ebp
27296     c3/return
27297 
27298 emit-float-output:  # out: (addr buffered-file), return-var: (addr stmt-var), dest-reg: (addr array byte)
27299     # . prologue
27300     55/push-ebp
27301     89/<- %ebp 4/r32/esp
27302     # . save registers
27303     50/push-eax
27304     #
27305     (emit-indent *(ebp+8) *Curr-block-depth)
27306     (write-buffered *(ebp+8) "f3 0f 10/->")
27307     (emit-subx-var-as-rm32 *(ebp+8) *(ebp+0xc))
27308     (write-buffered *(ebp+8) " ")
27309     (get Mu-registers *(ebp+0x10) 0xc "Mu-registers")  # => eax
27310     (write-int32-hex-buffered *(ebp+8) *eax)
27311     (write-buffered *(ebp+8) "/x32\n")
27312 $emit-float-output:end:
27313     # . restore registers
27314     58/pop-to-eax
27315     # . epilogue
27316     89/<- %esp 5/r32/ebp
27317     5d/pop-to-ebp
27318     c3/return
27319 
27320 is-mu-branch?:  # stmt: (addr stmt1) -> result/eax: boolean
27321     # . prologue
27322     55/push-ebp
27323     89/<- %ebp 4/r32/esp
27324     # . save registers
27325     51/push-ecx
27326     # ecx = lookup(stmt->operation)
27327     8b/-> *(ebp+8) 1/r32/ecx
27328     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
27329     89/<- %ecx 0/r32/eax
27330     # if (stmt->operation starts with "loop") return true
27331     (string-starts-with? %ecx "loop")  # => eax
27332     3d/compare-eax-and 0/imm32/false
27333     75/jump-if-not-equal $is-mu-branch?:end/disp8
27334     # if (stmt->operation starts with "break") return true
27335     (string-starts-with? %ecx "break")  # => eax
27336     3d/compare-eax-and 0/imm32/false
27337     75/jump-if-not-equal $is-mu-branch?:end/disp8
27338     # otherwise return (stmt->operation starts with "return")
27339     (string-starts-with? %ecx "return")  # => eax
27340 $is-mu-branch?:end:
27341     # . restore registers
27342     59/pop-to-ecx
27343     # . epilogue
27344     89/<- %esp 5/r32/ebp
27345     5d/pop-to-ebp
27346     c3/return
27347 
27348 emit-reverse-break:  # out: (addr buffered-file), stmt: (addr stmt1)
27349     # . prologue
27350     55/push-ebp
27351     89/<- %ebp 4/r32/esp
27352     # . save registers
27353     50/push-eax
27354     # eax = stmt
27355     8b/-> *(ebp+0xc) 0/r32/eax
27356     #
27357     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
27358     (get Reverse-branch %eax 0x10 "reverse-branch: ")  # => eax: (addr handle array byte)
27359     (emit-indent *(ebp+8) *Curr-block-depth)
27360     (lookup *eax *(eax+4))  # => eax
27361     (write-buffered *(ebp+8) %eax)
27362     (write-buffered *(ebp+8) " break/disp32\n")
27363 $emit-reverse-break:end:
27364     # . restore registers
27365     58/pop-to-eax
27366     # . epilogue
27367     89/<- %esp 5/r32/ebp
27368     5d/pop-to-ebp
27369     c3/return
27370 
27371 == data
27372 
27373 # Table from Mu branch instructions to the reverse SubX opcodes for them.
27374 Reverse-branch:  # (table (handle array byte) (handle array byte))
27375   # a table is a stream
27376   0x1c0/imm32/write
27377   0/imm32/read
27378   0x1c0/imm32/size
27379   # data
27380   0x11/imm32/alloc-id   _string-break-if-=/imm32                0x11/imm32/alloc-id   _string_0f_85_jump_label/imm32
27381   0x11/imm32/alloc-id   _string-loop-if-=/imm32                 0x11/imm32/alloc-id   _string_0f_85_jump_label/imm32
27382   0x11/imm32/alloc-id   _string-break-if-!=/imm32               0x11/imm32/alloc-id   _string_0f_84_jump_label/imm32
27383   0x11/imm32/alloc-id   _string-loop-if-!=/imm32                0x11/imm32/alloc-id   _string_0f_84_jump_label/imm32
27384   0x11/imm32/alloc-id   _string-break-if-</imm32                0x11/imm32/alloc-id   _string_0f_8d_jump_label/imm32
27385   0x11/imm32/alloc-id   _string-loop-if-</imm32                 0x11/imm32/alloc-id   _string_0f_8d_jump_label/imm32
27386   0x11/imm32/alloc-id   _string-break-if->/imm32                0x11/imm32/alloc-id   _string_0f_8e_jump_label/imm32
27387   0x11/imm32/alloc-id   _string-loop-if->/imm32                 0x11/imm32/alloc-id   _string_0f_8e_jump_label/imm32
27388   0x11/imm32/alloc-id   _string-break-if-<=/imm32               0x11/imm32/alloc-id   _string_0f_8f_jump_label/imm32
27389   0x11/imm32/alloc-id   _string-loop-if-<=/imm32                0x11/imm32/alloc-id   _string_0f_8f_jump_label/imm32
27390   0x11/imm32/alloc-id   _string-break-if->=/imm32               0x11/imm32/alloc-id   _string_0f_8c_jump_label/imm32
27391   0x11/imm32/alloc-id   _string-loop-if->=/imm32                0x11/imm32/alloc-id   _string_0f_8c_jump_label/imm32
27392   0x11/imm32/alloc-id   _string-break-if-addr</imm32            0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
27393   0x11/imm32/alloc-id   _string-loop-if-addr</imm32             0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
27394   0x11/imm32/alloc-id   _string-break-if-addr>/imm32            0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
27395   0x11/imm32/alloc-id   _string-loop-if-addr>/imm32             0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
27396   0x11/imm32/alloc-id   _string-break-if-addr<=/imm32           0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
27397   0x11/imm32/alloc-id   _string-loop-if-addr<=/imm32            0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
27398   0x11/imm32/alloc-id   _string-break-if-addr>=/imm32           0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
27399   0x11/imm32/alloc-id   _string-loop-if-addr>=/imm32            0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
27400   0x11/imm32/alloc-id   _string-break-if-float</imm32           0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
27401   0x11/imm32/alloc-id   _string-loop-if-float</imm32            0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
27402   0x11/imm32/alloc-id   _string-break-if-float>/imm32           0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
27403   0x11/imm32/alloc-id   _string-loop-if-float>/imm32            0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
27404   0x11/imm32/alloc-id   _string-break-if-float<=/imm32          0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
27405   0x11/imm32/alloc-id   _string-loop-if-float<=/imm32           0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
27406   0x11/imm32/alloc-id   _string-break-if-float>=/imm32          0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
27407   0x11/imm32/alloc-id   _string-loop-if-float>=/imm32           0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
27408 
27409 == code
27410 
27411 emit-unconditional-jump-to-depth:  # out: (addr buffered-file), vars: (addr stack live-var), depth: int, label-suffix: (addr array byte)
27412     # . prologue
27413     55/push-ebp
27414     89/<- %ebp 4/r32/esp
27415     # . save registers
27416     50/push-eax
27417     51/push-ecx
27418     52/push-edx
27419     53/push-ebx
27420     56/push-esi
27421     # ecx = vars
27422     8b/-> *(ebp+0xc) 1/r32/ecx
27423     # var eax: int = vars->top
27424     8b/-> *ecx 0/r32/eax
27425     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
27426     8d/copy-address *(ecx+eax-4) 6/r32/esi  # vars + 8 + vars->top - 12/Live-var-size
27427     # var min/ecx: (addr handle var) = vars->data
27428     8d/copy-address *(ecx+8) 1/r32/ecx
27429     # edx = depth
27430     8b/-> *(ebp+0x10) 2/r32/edx
27431     {
27432 $emit-unconditional-jump-to-depth:loop:
27433       # if (curr < min) break
27434       39/compare %esi 1/r32/ecx
27435       0f 82/jump-if-addr< break/disp32
27436       # var v/ebx: (addr var) = lookup(*curr)
27437       (lookup *esi *(esi+4))  # => eax
27438       89/<- %ebx 0/r32/eax
27439       # if (v->block-depth < until-block-depth) break
27440       39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
27441       0f 8c/jump-if-< break/disp32
27442       {
27443 $emit-unconditional-jump-to-depth:check:
27444         # if v->block-depth != until-block-depth, continue
27445         39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
27446         0f 85/jump-if-!= break/disp32
27447 $emit-unconditional-jump-to-depth:depth-found:
27448         # if v is not a literal, continue
27449         (size-of %ebx)  # => eax
27450         3d/compare-eax-and 0/imm32
27451         0f 85/jump-if-!= break/disp32
27452 $emit-unconditional-jump-to-depth:label-found:
27453         # emit unconditional jump, then return
27454         (emit-indent *(ebp+8) *Curr-block-depth)
27455         (write-buffered *(ebp+8) "e9/jump ")
27456         (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
27457         (write-buffered *(ebp+8) %eax)
27458         (write-buffered *(ebp+8) ":")
27459         (write-buffered *(ebp+8) *(ebp+0x14))
27460         (write-buffered *(ebp+8) "/disp32\n")
27461         eb/jump $emit-unconditional-jump-to-depth:end/disp8
27462       }
27463       # curr -= 12
27464       81 5/subop/subtract %esi 0xc/imm32
27465       e9/jump loop/disp32
27466     }
27467     # TODO: error if no label at 'depth' was found
27468 $emit-unconditional-jump-to-depth:end:
27469     # . restore registers
27470     5e/pop-to-esi
27471     5b/pop-to-ebx
27472     5a/pop-to-edx
27473     59/pop-to-ecx
27474     58/pop-to-eax
27475     # . epilogue
27476     89/<- %esp 5/r32/ebp
27477     5d/pop-to-ebp
27478     c3/return
27479 
27480 # emit clean-up code for 'vars' until some block depth
27481 # doesn't actually modify 'vars' so we need traverse manually inside the stack
27482 emit-cleanup-code-until-depth:  # out: (addr buffered-file), vars: (addr stack live-var), until-block-depth: int
27483     # . prologue
27484     55/push-ebp
27485     89/<- %ebp 4/r32/esp
27486     # . save registers
27487     50/push-eax
27488     51/push-ecx
27489     52/push-edx
27490     53/push-ebx
27491     56/push-esi
27492 #?     (write-buffered Stderr "--- cleanup\n")
27493 #?     (flush Stderr)
27494     # ecx = vars
27495     8b/-> *(ebp+0xc) 1/r32/ecx
27496     # var esi: int = vars->top
27497     8b/-> *ecx 6/r32/esi
27498     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
27499     8d/copy-address *(ecx+esi-4) 6/r32/esi  # vars + 8 + vars->top - 12/Live-var-size
27500     # var min/ecx: (addr handle var) = vars->data
27501     81 0/subop/add %ecx 8/imm32
27502     # edx = until-block-depth
27503     8b/-> *(ebp+0x10) 2/r32/edx
27504     {
27505 $emit-cleanup-code-until-depth:loop:
27506       # if (curr < min) break
27507       39/compare %esi 1/r32/ecx
27508       0f 82/jump-if-addr< break/disp32
27509       # var v/ebx: (addr var) = lookup(*curr)
27510       (lookup *esi *(esi+4))  # => eax
27511       89/<- %ebx 0/r32/eax
27512 #?       (lookup *ebx *(ebx+4))  # Var-name
27513 #?       (write-buffered Stderr "var ")
27514 #?       (write-buffered Stderr %eax)
27515 #?       (write-buffered Stderr Newline)
27516 #?       (flush Stderr)
27517       # if (v->block-depth < until-block-depth) break
27518       39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
27519       0f 8c/jump-if-< break/disp32
27520       # if v is in a register
27521       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
27522       {
27523         0f 84/jump-if-= break/disp32
27524         {
27525 $emit-cleanup-code-until-depth:check-for-previous-spill:
27526           8b/-> *(esi+8) 0/r32/eax  # Live-var-register-spilled
27527           3d/compare-eax-and 0/imm32/false
27528           74/jump-if-= break/disp8
27529 $emit-cleanup-code-until-depth:reclaim-var-in-register:
27530           (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
27531           (emit-pop-register *(ebp+8) %eax)
27532         }
27533         eb/jump $emit-cleanup-code-until-depth:continue/disp8
27534       }
27535       # otherwise v is on the stack
27536       {
27537         75/jump-if-!= break/disp8
27538 $emit-cleanup-code-until-depth:var-on-stack:
27539         (size-of %ebx)  # => eax
27540         # don't emit code for labels
27541         3d/compare-eax-and 0/imm32
27542         74/jump-if-= break/disp8
27543 $emit-cleanup-code-until-depth:reclaim-var-on-stack:
27544         (emit-indent *(ebp+8) *Curr-block-depth)
27545         (write-buffered *(ebp+8) "81 0/subop/add %esp ")
27546         (write-int32-hex-buffered *(ebp+8) %eax)
27547         (write-buffered *(ebp+8) "/imm32\n")
27548       }
27549 $emit-cleanup-code-until-depth:continue:
27550       # curr -= 12
27551       81 5/subop/subtract %esi 0xc/imm32
27552       e9/jump loop/disp32
27553     }
27554 $emit-cleanup-code-until-depth:end:
27555     # . restore registers
27556     5e/pop-to-esi
27557     5b/pop-to-ebx
27558     5a/pop-to-edx
27559     59/pop-to-ecx
27560     58/pop-to-eax
27561     # . epilogue
27562     89/<- %esp 5/r32/ebp
27563     5d/pop-to-ebp
27564     c3/return
27565 
27566 # emit clean-up code for 'vars' that don't conflict with output registers
27567 # doesn't actually modify 'vars' so we need traverse manually inside the stack
27568 emit-cleanup-code-for-non-outputs:  # out: (addr buffered-file), vars: (addr stack live-var), fn: (addr function)
27569     # . prologue
27570     55/push-ebp
27571     89/<- %ebp 4/r32/esp
27572     # . save registers
27573     50/push-eax
27574     51/push-ecx
27575     52/push-edx
27576     53/push-ebx
27577     56/push-esi
27578     57/push-edi
27579     # ecx = vars
27580     8b/-> *(ebp+0xc) 1/r32/ecx
27581     # var esi: int = vars->top
27582     8b/-> *ecx 6/r32/esi
27583     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
27584     8d/copy-address *(ecx+esi-4) 6/r32/esi  # vars + 8 + vars->top - 12/Live-var-size
27585     # var min/ecx: (addr handle var) = vars->data
27586     81 0/subop/add %ecx 8/imm32
27587     {
27588 $emit-cleanup-code-for-non-outputs:loop:
27589       # if (curr < min) break
27590       39/compare %esi 1/r32/ecx
27591       0f 82/jump-if-addr< break/disp32
27592       # var v/ebx: (addr var) = lookup(*curr)
27593       (lookup *esi *(esi+4))  # => eax
27594       89/<- %ebx 0/r32/eax
27595       # if v is in a register
27596       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
27597       {
27598         0f 84/jump-if-= break/disp32
27599         {
27600 $emit-cleanup-code-for-non-outputs:check-for-previous-spill:
27601           8b/-> *(esi+8) 0/r32/eax  # Live-var-register-spilled
27602           3d/compare-eax-and 0/imm32/false
27603           0f 84/jump-if-= break/disp32
27604 $emit-cleanup-code-for-non-outputs:reclaim-var-in-register:
27605           # var reg/edi: (addr array name) = v->register
27606           (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
27607           89/<- %edi 0/r32/eax
27608           # if reg is not in function outputs, emit a pop
27609           (reg-in-function-outputs? *(ebp+0x10) %edi)  # => eax
27610           3d/compare-eax-and 0/imm32/false
27611           {
27612             75/jump-if-!= break/disp8
27613             (emit-pop-register *(ebp+8) %edi)
27614             eb/jump $emit-cleanup-code-for-non-outputs:reclaim-var-in-register-done/disp8
27615           }
27616           # otherwise just drop it from the stack
27617           (emit-indent *(ebp+8) *Curr-block-depth)
27618           (write-buffered *(ebp+8) "81 0/subop/add %esp 4/imm32\n")
27619         }
27620 $emit-cleanup-code-for-non-outputs:reclaim-var-in-register-done:
27621         eb/jump $emit-cleanup-code-for-non-outputs:continue/disp8
27622       }
27623       # otherwise v is on the stack
27624       {
27625         75/jump-if-!= break/disp8
27626 $emit-cleanup-code-for-non-outputs:var-on-stack:
27627         (size-of %ebx)  # => eax
27628         # don't emit code for labels
27629         3d/compare-eax-and 0/imm32
27630         74/jump-if-= break/disp8
27631 $emit-cleanup-code-for-non-outputs:reclaim-var-on-stack:
27632         (emit-indent *(ebp+8) *Curr-block-depth)
27633         (write-buffered *(ebp+8) "81 0/subop/add %esp ")
27634         (write-int32-hex-buffered *(ebp+8) %eax)
27635         (write-buffered *(ebp+8) "/imm32\n")
27636       }
27637 $emit-cleanup-code-for-non-outputs:continue:
27638       # curr -= 12
27639       81 5/subop/subtract %esi 0xc/imm32
27640       e9/jump loop/disp32
27641     }
27642 $emit-cleanup-code-for-non-outputs:end:
27643     # . restore registers
27644     5f/pop-to-edi
27645     5e/pop-to-esi
27646     5b/pop-to-ebx
27647     5a/pop-to-edx
27648     59/pop-to-ecx
27649     58/pop-to-eax
27650     # . epilogue
27651     89/<- %esp 5/r32/ebp
27652     5d/pop-to-ebp
27653     c3/return
27654 
27655 emit-push-register:  # out: (addr buffered-file), reg: (addr array byte)
27656     # . prologue
27657     55/push-ebp
27658     89/<- %ebp 4/r32/esp
27659     # eax = reg
27660     8b/-> *(ebp+0xc) 0/r32/eax
27661     # var prefix/eax: byte = reg->data[0]
27662     8a/copy-byte *(eax+4) 0/r32/AL
27663     81 4/subop/and %eax 0xff/imm32
27664     # if (prefix == 'x') push xmm register
27665     {
27666       3d/compare-eax-and 0x78/imm32/x
27667       0f 85/jump-if-!= break/disp32
27668       # TODO validate register
27669       (emit-indent *(ebp+8) *Curr-block-depth)
27670       (write-buffered *(ebp+8) "81 5/subop/subtract %esp 4/imm32\n")
27671       (emit-indent *(ebp+8) *Curr-block-depth)
27672       (write-buffered *(ebp+8) "f3 0f 11/<- *esp ")
27673       # var prefix/eax: byte = reg->data[3]
27674       8b/-> *(ebp+0xc) 0/r32/eax
27675       8a/copy-byte *(eax+7) 0/r32/AL
27676       81 4/subop/and %eax 0xff/imm32
27677       (write-byte-buffered *(ebp+8) %eax)
27678       (write-buffered *(ebp+8) "/x32\n")
27679       e9/jump $emit-push-register:end/disp32
27680     }
27681     # otherwise push gp register
27682     (emit-indent *(ebp+8) *Curr-block-depth)
27683     (write-buffered *(ebp+8) "ff 6/subop/push %")
27684     (write-buffered *(ebp+8) *(ebp+0xc))
27685     (write-buffered *(ebp+8) Newline)
27686 $emit-push-register:end:
27687     # . epilogue
27688     89/<- %esp 5/r32/ebp
27689     5d/pop-to-ebp
27690     c3/return
27691 
27692 emit-pop-register:  # out: (addr buffered-file), reg: (addr array byte)
27693     # . prologue
27694     55/push-ebp
27695     89/<- %ebp 4/r32/esp
27696     # . save registers
27697     50/push-eax
27698     # eax = reg
27699     8b/-> *(ebp+0xc) 0/r32/eax
27700     # var prefix/eax: byte = reg->data[0]
27701     8a/copy-byte *(eax+4) 0/r32/AL
27702     81 4/subop/and %eax 0xff/imm32
27703     # if (prefix == 'x') pop to xmm register
27704     {
27705       3d/compare-eax-and 0x78/imm32/x
27706       0f 85/jump-if-!= break/disp32
27707       # TODO validate register
27708       (emit-indent *(ebp+8) *Curr-block-depth)
27709       (write-buffered *(ebp+8) "f3 0f 10/-> *esp ")
27710       # var prefix/eax: byte = reg->data[3]
27711       8b/-> *(ebp+0xc) 0/r32/eax
27712       8a/copy-byte *(eax+7) 0/r32/AL
27713       81 4/subop/and %eax 0xff/imm32
27714       (write-byte-buffered *(ebp+8) %eax)
27715       (write-buffered *(ebp+8) "/x32\n")
27716       (emit-indent *(ebp+8) *Curr-block-depth)
27717       (write-buffered *(ebp+8) "81 0/subop/add %esp 4/imm32\n")
27718       e9/jump $emit-pop-register:end/disp32
27719     }
27720     # otherwise pop to gp register
27721     (emit-indent *(ebp+8) *Curr-block-depth)
27722     (write-buffered *(ebp+8) "8f 0/subop/pop %")
27723     (write-buffered *(ebp+8) *(ebp+0xc))
27724     (write-buffered *(ebp+8) Newline)
27725 $emit-pop-register:end:
27726     # . restore registers
27727     58/pop-to-eax
27728     # . epilogue
27729     89/<- %esp 5/r32/ebp
27730     5d/pop-to-ebp
27731     c3/return
27732 
27733 # emit clean-up code for 'vars' until a given label is encountered
27734 # doesn't actually modify 'vars' so we need traverse manually inside the stack
27735 emit-cleanup-code-until-target:  # out: (addr buffered-file), vars: (addr stack live-var), until-block-label: (addr array byte)
27736     # . prologue
27737     55/push-ebp
27738     89/<- %ebp 4/r32/esp
27739     # . save registers
27740     50/push-eax
27741     51/push-ecx
27742     52/push-edx
27743     53/push-ebx
27744     # ecx = vars
27745     8b/-> *(ebp+0xc) 1/r32/ecx
27746     # var eax: int = vars->top
27747     8b/-> *ecx 0/r32/eax
27748     # var curr/edx: (addr handle var) = &vars->data[vars->top - 12]
27749     8d/copy-address *(ecx+eax-4) 2/r32/edx  # vars + 8 + vars->top - 12/Live-var-size
27750     # var min/ecx: (addr handle var) = vars->data
27751     81 0/subop/add %ecx 8/imm32
27752     {
27753 $emit-cleanup-code-until-target:loop:
27754       # if (curr < min) break
27755       39/compare %edx 1/r32/ecx
27756       0f 82/jump-if-addr< break/disp32
27757       # var v/ebx: (handle var) = lookup(*curr)
27758       (lookup *edx *(edx+4))  # => eax
27759       89/<- %ebx 0/r32/eax
27760       # if (v->name == until-block-label) break
27761       (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
27762       (string-equal? %eax *(ebp+0x10))  # => eax
27763       3d/compare-eax-and 0/imm32/false
27764       0f 85/jump-if-!= break/disp32
27765       # if v is in a register
27766       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
27767       {
27768         0f 84/jump-if-= break/disp32
27769         {
27770 $emit-cleanup-code-until-target:check-for-previous-spill:
27771           8b/-> *(edx+8) 0/r32/eax  # Live-var-register-spilled
27772           3d/compare-eax-and 0/imm32/false
27773           74/jump-if-= break/disp8
27774 $emit-cleanup-code-until-target:reclaim-var-in-register:
27775           (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
27776           (emit-pop-register *(ebp+8) %eax)
27777         }
27778         eb/jump $emit-cleanup-code-until-target:continue/disp8
27779       }
27780       # otherwise v is on the stack
27781       {
27782         75/jump-if-!= break/disp8
27783 $emit-cleanup-code-until-target:reclaim-var-on-stack:
27784         (size-of %ebx)  # => eax
27785         # don't emit code for labels
27786         3d/compare-eax-and 0/imm32
27787         74/jump-if-= break/disp8
27788         #
27789         (emit-indent *(ebp+8) *Curr-block-depth)
27790         (write-buffered *(ebp+8) "81 0/subop/add %esp ")
27791         (write-int32-hex-buffered *(ebp+8) %eax)
27792         (write-buffered *(ebp+8) "/imm32\n")
27793       }
27794 $emit-cleanup-code-until-target:continue:
27795       # curr -= 12
27796       81 5/subop/subtract %edx 0xc/imm32
27797       e9/jump loop/disp32
27798     }
27799 $emit-cleanup-code-until-target:end:
27800     # . restore registers
27801     5b/pop-to-ebx
27802     5a/pop-to-edx
27803     59/pop-to-ecx
27804     58/pop-to-eax
27805     # . epilogue
27806     89/<- %esp 5/r32/ebp
27807     5d/pop-to-ebp
27808     c3/return
27809 
27810 # update Curr-local-stack-offset assuming vars until some block depth are popped
27811 # doesn't actually modify 'vars', so we need traverse manually inside the stack
27812 clean-up-stack-offset-state:  # vars: (addr stack live-var), until-block-depth: int
27813     # . prologue
27814     55/push-ebp
27815     89/<- %ebp 4/r32/esp
27816     # . save registers
27817     50/push-eax
27818     51/push-ecx
27819     52/push-edx
27820     53/push-ebx
27821     56/push-esi
27822     # ecx = vars
27823     8b/-> *(ebp+8) 1/r32/ecx
27824     # var esi: int = vars->top
27825     8b/-> *ecx 6/r32/esi
27826     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
27827     8d/copy-address *(ecx+esi-4) 6/r32/esi  # vars + 8 + vars->top - 12/Live-var-size
27828     # var min/ecx: (addr handle var) = vars->data
27829     81 0/subop/add %ecx 8/imm32
27830     # edx = until-block-depth
27831     8b/-> *(ebp+0xc) 2/r32/edx
27832     {
27833 $clean-up-stack-offset-state:loop:
27834       # if (curr < min) break
27835       39/compare %esi 1/r32/ecx
27836       0f 82/jump-if-addr< break/disp32
27837       # var v/ebx: (addr var) = lookup(*curr)
27838       (lookup *esi *(esi+4))  # => eax
27839       89/<- %ebx 0/r32/eax
27840       # if (v->block-depth < until-block-depth) break
27841       39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
27842       0f 8c/jump-if-< break/disp32
27843       # if v is in a register
27844       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
27845       {
27846         0f 84/jump-if-= break/disp32
27847         {
27848 $clean-up-stack-offset-state:check-for-previous-spill:
27849           8b/-> *(esi+8) 0/r32/eax  # Live-var-register-spilled
27850           3d/compare-eax-and 0/imm32/false
27851           74/jump-if-= break/disp8
27852 $clean-up-stack-offset-state:reclaim-var-in-register:
27853           81 0/subop/add *Curr-local-stack-offset 4/imm32
27854         }
27855         eb/jump $clean-up-stack-offset-state:continue/disp8
27856       }
27857       # otherwise v is on the stack
27858       {
27859         75/jump-if-!= break/disp8
27860 $clean-up-stack-offset-state:var-on-stack:
27861         (size-of %ebx)  # => eax
27862         01/add-to *Curr-local-stack-offset 0/r32/eax
27863       }
27864 $clean-up-stack-offset-state:continue:
27865       # curr -= 12
27866       81 5/subop/subtract %esi 0xc/imm32
27867       e9/jump loop/disp32
27868     }
27869 $clean-up-stack-offset-state:end:
27870     # . restore registers
27871     5e/pop-to-esi
27872     5b/pop-to-ebx
27873     5a/pop-to-edx
27874     59/pop-to-ecx
27875     58/pop-to-eax
27876     # . epilogue
27877     89/<- %esp 5/r32/ebp
27878     5d/pop-to-ebp
27879     c3/return
27880 
27881 # Return true if there isn't a variable in 'vars' with the same block-depth
27882 # and register as 'v'.
27883 # 'v' is guaranteed not to be within 'vars'.
27884 not-yet-spilled-this-block?:  # v: (addr var), vars: (addr stack live-var) -> result/eax: boolean
27885     # . prologue
27886     55/push-ebp
27887     89/<- %ebp 4/r32/esp
27888     # . save registers
27889     51/push-ecx
27890     52/push-edx
27891     53/push-ebx
27892     56/push-esi
27893     57/push-edi
27894     # ecx = vars
27895     8b/-> *(ebp+0xc) 1/r32/ecx
27896     # var eax: int = vars->top
27897     8b/-> *ecx 0/r32/eax
27898     # var curr/edx: (addr handle var) = &vars->data[vars->top - 12]
27899     8d/copy-address *(ecx+eax-4) 2/r32/edx  # vars + 8 + vars->top - 12/Live-var-size
27900     # var min/ecx: (addr handle var) = vars->data
27901     8d/copy-address *(ecx+8) 1/r32/ecx
27902     # var depth/ebx: int = v->block-depth
27903     8b/-> *(ebp+8) 3/r32/ebx
27904     8b/-> *(ebx+0x10) 3/r32/ebx  # Var-block-depth
27905     # var needle/esi: (addr array byte) = v->register
27906     8b/-> *(ebp+8) 6/r32/esi
27907     (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
27908     89/<- %esi 0/r32/eax
27909     {
27910 $not-yet-spilled-this-block?:loop:
27911       # if (curr < min) break
27912       39/compare %edx 1/r32/ecx
27913       0f 82/jump-if-addr< break/disp32
27914       # var cand/edi: (addr var) = lookup(*curr)
27915       (lookup *edx *(edx+4))  # => eax
27916       89/<- %edi 0/r32/eax
27917       # if (cand->block-depth < depth) break
27918       39/compare *(edi+0x10) 3/r32/ebx  # Var-block-depth
27919       0f 8c/jump-if-< break/disp32
27920       # var cand-reg/edi: (array array byte) = cand->reg
27921       (lookup *(edi+0x18) *(edi+0x1c))  # Var-register Var-register => eax
27922       89/<- %edi 0/r32/eax
27923       # if (cand-reg == null) continue
27924       {
27925 $not-yet-spilled-this-block?:check-reg:
27926         81 7/subop/compare %edi 0/imm32
27927         0f 84/jump-if-= break/disp32
27928         # if (cand-reg == needle) return true
27929         (string-equal? %esi %edi)  # => eax
27930         3d/compare-eax-and 0/imm32/false
27931         74/jump-if-= break/disp8
27932 $not-yet-spilled-this-block?:return-false:
27933         b8/copy-to-eax 0/imm32/false
27934         eb/jump $not-yet-spilled-this-block?:end/disp8
27935       }
27936 $not-yet-spilled-this-block?:continue:
27937       # curr -= 12
27938       81 5/subop/subtract %edx 0xc/imm32
27939       e9/jump loop/disp32
27940     }
27941 $not-yet-spilled-this-block?:return-true:
27942     # return true
27943     b8/copy-to-eax 1/imm32/true
27944 $not-yet-spilled-this-block?:end:
27945     # . restore registers
27946     5f/pop-to-edi
27947     5e/pop-to-esi
27948     5b/pop-to-ebx
27949     5a/pop-to-edx
27950     59/pop-to-ecx
27951     # . epilogue
27952     89/<- %esp 5/r32/ebp
27953     5d/pop-to-ebp
27954     c3/return
27955 
27956 # could the register of 'v' ever be written to by one of the vars in fn-outputs?
27957 will-not-write-some-register?:  # v: (addr var), stmts: (addr list stmt), fn: (addr function) -> result/eax: boolean
27958     # . prologue
27959     55/push-ebp
27960     89/<- %ebp 4/r32/esp
27961     # eax = v
27962     8b/-> *(ebp+8) 0/r32/eax
27963     # var reg/eax: (addr array byte) = lookup(v->register)
27964     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
27965     # var target/eax: (addr var) = find-register(fn-outputs, reg)
27966     (find-register *(ebp+0x10) %eax)  # => eax
27967     # if (target == 0) return true
27968     {
27969       3d/compare-eax-and 0/imm32
27970       75/jump-if-!= break/disp8
27971       b8/copy-to-eax 1/imm32/true
27972       eb/jump $will-not-write-some-register?:end/disp8
27973     }
27974     # return !assigns-in-stmts?(stmts, target)
27975     (assigns-in-stmts? *(ebp+0xc) %eax)  # => eax
27976     3d/compare-eax-and 0/imm32/false
27977     # assume: true = 1, so no need to mask with 0x000000ff
27978     0f 94/set-if-= %al
27979 $will-not-write-some-register?:end:
27980     # . epilogue
27981     89/<- %esp 5/r32/ebp
27982     5d/pop-to-ebp
27983     c3/return
27984 
27985 # return fn output with matching register
27986 # always returns false if 'reg' is null
27987 find-register:  # fn: (addr function), reg: (addr array byte) -> result/eax: (addr var)
27988     # . prologue
27989     55/push-ebp
27990     89/<- %ebp 4/r32/esp
27991     # . save registers
27992     51/push-ecx
27993     # var curr/ecx: (addr list var) = lookup(fn->outputs)
27994     8b/-> *(ebp+8) 1/r32/ecx
27995     (lookup *(ecx+0x10) *(ecx+0x14))  # Function-outputs Function-outputs => eax
27996     89/<- %ecx 0/r32/eax
27997     {
27998 $find-register:loop:
27999       # if (curr == 0) break
28000       81 7/subop/compare %ecx 0/imm32
28001       74/jump-if-= break/disp8
28002       # eax = curr->value->register
28003       (lookup *ecx *(ecx+4))  # List-value List-value => eax
28004       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
28005       # if (eax == reg) return curr->value
28006 $find-register:compare:
28007       (string-equal? *(ebp+0xc) %eax)  # => eax
28008       {
28009         3d/compare-eax-and 0/imm32/false
28010         74/jump-if-= break/disp8
28011 $find-register:found:
28012         (lookup *ecx *(ecx+4))  # List-value List-value => eax
28013         eb/jump $find-register:end/disp8
28014       }
28015       # curr = lookup(curr->next)
28016       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
28017       89/<- %ecx 0/r32/eax
28018       #
28019       eb/jump loop/disp8
28020     }
28021 $find-register:end:
28022     # . restore registers
28023     59/pop-to-ecx
28024     # . epilogue
28025     89/<- %esp 5/r32/ebp
28026     5d/pop-to-ebp
28027     c3/return
28028 
28029 assigns-in-stmts?:  # stmts: (addr list stmt), v: (addr var) -> result/eax: boolean
28030     # . prologue
28031     55/push-ebp
28032     89/<- %ebp 4/r32/esp
28033     # . save registers
28034     51/push-ecx
28035     # var curr/ecx: (addr list stmt) = stmts
28036     8b/-> *(ebp+8) 1/r32/ecx
28037     {
28038       # if (curr == 0) break
28039       81 7/subop/compare %ecx 0/imm32
28040       74/jump-if-= break/disp8
28041       # if assigns-in-stmt?(curr->value, v) return true
28042       (lookup *ecx *(ecx+4))  # List-value List-value => eax
28043       (assigns-in-stmt? %eax *(ebp+0xc))  # => eax
28044       3d/compare-eax-and 0/imm32/false
28045       75/jump-if-!= break/disp8
28046       # curr = lookup(curr->next)
28047       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
28048       89/<- %ecx 0/r32/eax
28049       #
28050       eb/jump loop/disp8
28051     }
28052 $assigns-in-stmts?:end:
28053     # . restore registers
28054     59/pop-to-ecx
28055     # . epilogue
28056     89/<- %esp 5/r32/ebp
28057     5d/pop-to-ebp
28058     c3/return
28059 
28060 assigns-in-stmt?:  # stmt: (addr stmt), v: (addr var) -> result/eax: boolean
28061     # . prologue
28062     55/push-ebp
28063     89/<- %ebp 4/r32/esp
28064     # . save registers
28065     51/push-ecx
28066     # ecx = stmt
28067     8b/-> *(ebp+8) 1/r32/ecx
28068     # if stmt is a stmt1, return assigns-in-stmt-vars?(stmt->outputs, v)
28069     {
28070       81 7/subop/compare *ecx 1/imm32/stmt1  # Stmt-tag
28071       75/jump-if-!= break/disp8
28072       (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
28073       (assigns-in-stmt-vars? %eax *(ebp+0xc))  # => eax
28074       eb/jump $assigns-in-stmt?:end/disp8
28075     }
28076     # if stmt is a block, return assigns-in-stmts?(stmt->stmts, v)
28077     {
28078       81 7/subop/compare *ecx 0/imm32/block  # Stmt-tag
28079       75/jump-if-!= break/disp8
28080       (lookup *(ecx+4) *(ecx+8))  # Block-stmts Block-stmts => eax
28081       (assigns-in-stmts? %eax *(ebp+0xc))  # => eax
28082       eb/jump $assigns-in-stmt?:end/disp8
28083     }
28084     # otherwise return false
28085     b8/copy 0/imm32/false
28086 $assigns-in-stmt?:end:
28087     # . restore registers
28088     59/pop-to-ecx
28089     # . epilogue
28090     89/<- %esp 5/r32/ebp
28091     5d/pop-to-ebp
28092     c3/return
28093 
28094 assigns-in-stmt-vars?:  # stmt-var: (addr stmt-var), v: (addr var) -> result/eax: boolean
28095     # . prologue
28096     55/push-ebp
28097     89/<- %ebp 4/r32/esp
28098     # . save registers
28099     51/push-ecx
28100     # var curr/ecx: (addr stmt-var) = stmt-var
28101     8b/-> *(ebp+8) 1/r32/ecx
28102     {
28103       # if (curr == 0) break
28104       81 7/subop/compare %ecx 0/imm32
28105       74/jump-if-= break/disp8
28106       # eax = lookup(curr->value)
28107       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
28108       # if (eax == v  &&  curr->is-deref? == false) return true
28109       {
28110         39/compare *(ebp+0xc) 0/r32/eax
28111         75/jump-if-!= break/disp8
28112         81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
28113         75/jump-if-!= break/disp8
28114         b8/copy-to-eax 1/imm32/true
28115         eb/jump $assigns-in-stmt-vars?:end/disp8
28116       }
28117       # curr = lookup(curr->next)
28118       (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
28119       89/<- %ecx 0/r32/eax
28120       #
28121       eb/jump loop/disp8
28122     }
28123 $assigns-in-stmt-vars?:end:
28124     # . restore registers
28125     59/pop-to-ecx
28126     # . epilogue
28127     89/<- %esp 5/r32/ebp
28128     5d/pop-to-ebp
28129     c3/return
28130 
28131 # is there a var before 'v' with the same block-depth and register on the 'vars' stack?
28132 # v is guaranteed to be within vars
28133 # 'start' is provided as an optimization, a pointer within vars
28134 # *start == v
28135 same-register-spilled-before?:  # v: (addr var), vars: (addr stack (handle var)), start: (addr var) -> result/eax: boolean
28136     # . prologue
28137     55/push-ebp
28138     89/<- %ebp 4/r32/esp
28139     # . save registers
28140     51/push-ecx
28141     52/push-edx
28142     53/push-ebx
28143     56/push-esi
28144     57/push-edi
28145     # ecx = v
28146     8b/-> *(ebp+8) 1/r32/ecx
28147     # var reg/edx: (addr array byte) = lookup(v->register)
28148     (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
28149     89/<- %edx 0/r32/eax
28150     # var depth/ebx: int = v->block-depth
28151     8b/-> *(ecx+0x10) 3/r32/ebx  # Var-block-depth
28152     # var min/ecx: (addr handle var) = vars->data
28153     8b/-> *(ebp+0xc) 1/r32/ecx
28154     81 0/subop/add %ecx 8/imm32
28155     # TODO: check that start >= min and start < &vars->data[top]
28156     # TODO: check that *start == v
28157     # var curr/esi: (addr handle var) = start
28158     8b/-> *(ebp+0x10) 6/r32/esi
28159     # curr -= 8
28160     81 5/subop/subtract %esi 8/imm32
28161     {
28162 $same-register-spilled-before?:loop:
28163       # if (curr < min) break
28164       39/compare %esi 1/r32/ecx
28165       0f 82/jump-if-addr< break/disp32
28166       # var x/eax: (addr var) = lookup(*curr)
28167       (lookup *esi *(esi+4))  # => eax
28168       # if (x->block-depth < depth) break
28169       39/compare *(eax+0x10) 3/r32/ebx  # Var-block-depth
28170       0f 8c/jump-if-< break/disp32
28171       # if (x->register == 0) continue
28172       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
28173       74/jump-if-= $same-register-spilled-before?:continue/disp8
28174       # if (x->register == reg) return true
28175       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
28176       (string-equal? %eax %edx)  # => eax
28177       3d/compare-eax-and 0/imm32/false
28178       b8/copy-to-eax 1/imm32/true
28179       75/jump-if-!= $same-register-spilled-before?:end/disp8
28180 $same-register-spilled-before?:continue:
28181       # curr -= 8
28182       81 5/subop/subtract %esi 8/imm32
28183       e9/jump loop/disp32
28184     }
28185 $same-register-spilled-before?:false:
28186     b8/copy-to-eax 0/imm32/false
28187 $same-register-spilled-before?:end:
28188     # . restore registers
28189     5f/pop-to-edi
28190     5e/pop-to-esi
28191     5b/pop-to-ebx
28192     5a/pop-to-edx
28193     59/pop-to-ecx
28194     # . epilogue
28195     89/<- %esp 5/r32/ebp
28196     5d/pop-to-ebp
28197     c3/return
28198 
28199 # clean up global state for 'vars' until some block depth (inclusive)
28200 clean-up-blocks:  # vars: (addr stack live-var), until-block-depth: int, fn: (addr function)
28201     # . prologue
28202     55/push-ebp
28203     89/<- %ebp 4/r32/esp
28204     # . save registers
28205     50/push-eax
28206     51/push-ecx
28207     56/push-esi
28208     # esi = vars
28209     8b/-> *(ebp+8) 6/r32/esi
28210     # ecx = until-block-depth
28211     8b/-> *(ebp+0xc) 1/r32/ecx
28212     {
28213 $clean-up-blocks:reclaim-loop:
28214       # if (vars->top <= 0) break
28215       8b/-> *esi 0/r32/eax  # Stack-top
28216       3d/compare-eax-and 0/imm32
28217       0f 8e/jump-if-<= break/disp32
28218       # var v/eax: (addr var) = lookup(vars[vars->top-12])
28219       (lookup *(esi+eax-4) *(esi+eax))  # vars + 8 + vars->top - 12 => eax
28220       # if (v->block-depth < until-block-depth) break
28221       39/compare *(eax+0x10) 1/r32/ecx  # Var-block-depth
28222       0f 8c/jump-if-< break/disp32
28223       (pop %esi)  # => eax
28224       (pop %esi)  # => eax
28225       (pop %esi)  # => eax
28226       e9/jump loop/disp32
28227     }
28228 $clean-up-blocks:end:
28229     # . restore registers
28230     5e/pop-to-esi
28231     59/pop-to-ecx
28232     58/pop-to-eax
28233     # . epilogue
28234     89/<- %esp 5/r32/ebp
28235     5d/pop-to-ebp
28236     c3/return
28237 
28238 reg-in-function-outputs?:  # fn: (addr function), target: (addr array byte) -> result/eax: boolean
28239     # . prologue
28240     55/push-ebp
28241     89/<- %ebp 4/r32/esp
28242     # . save registers
28243     51/push-ecx
28244     # var curr/ecx: (addr list var) = lookup(fn->outputs)
28245     8b/-> *(ebp+8) 0/r32/eax
28246     (lookup *(eax+0x10) *(eax+0x14))  # Function-outputs Function-outputs => eax
28247     89/<- %ecx 0/r32/eax
28248     # while curr != null
28249     {
28250       81 7/subop/compare %ecx 0/imm32
28251       74/jump-if-= break/disp8
28252       # var v/eax: (addr var) = lookup(curr->value)
28253       (lookup *ecx *(ecx+4))  # List-value List-value => eax
28254       # var reg/eax: (addr array byte) = lookup(v->register)
28255       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
28256       # if (reg == target) return true
28257       (string-equal? %eax *(ebp+0xc))  # => eax
28258       3d/compare-eax-and 0/imm32/false
28259       75/jump-if-!= $reg-in-function-outputs?:end/disp8
28260       # curr = curr->next
28261       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
28262       89/<- %ecx 0/r32/eax
28263       #
28264       eb/jump loop/disp8
28265     }
28266     # return false
28267     b8/copy-to-eax 0/imm32
28268 $reg-in-function-outputs?:end:
28269     # . restore registers
28270     59/pop-to-ecx
28271     # . epilogue
28272     89/<- %esp 5/r32/ebp
28273     5d/pop-to-ebp
28274     c3/return
28275 
28276 emit-subx-var-def:  # out: (addr buffered-file), stmt: (addr stmt)
28277     # . prologue
28278     55/push-ebp
28279     89/<- %ebp 4/r32/esp
28280     # . save registers
28281     50/push-eax
28282     51/push-ecx
28283     52/push-edx
28284     # eax = stmt
28285     8b/-> *(ebp+0xc) 0/r32/eax
28286     # var v/ecx: (addr var)
28287     (lookup *(eax+4) *(eax+8))  # Vardef-var Vardef-var => eax
28288     89/<- %ecx 0/r32/eax
28289     # v->block-depth = *Curr-block-depth
28290     8b/-> *Curr-block-depth 0/r32/eax
28291     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
28292     # var n/edx: int = size-of(stmt->var)
28293     (size-of %ecx)  # => eax
28294     89/<- %edx 0/r32/eax
28295     # *Curr-local-stack-offset -= n
28296     29/subtract-from *Curr-local-stack-offset 2/r32/edx
28297     # v->offset = *Curr-local-stack-offset
28298     8b/-> *Curr-local-stack-offset 0/r32/eax
28299     89/<- *(ecx+0x14) 0/r32/eax  # Var-offset
28300     # if v is an array, do something special to initialize it
28301     {
28302       (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
28303       (is-mu-array? %eax)  # => eax
28304       3d/compare-eax-and 0/imm32/false
28305       0f 84/jump-if-= break/disp32
28306       # var array-size-without-size/edx: int = n-4
28307       81 5/subop/subtract %edx 4/imm32
28308       #
28309       (emit-array-data-initialization *(ebp+8) %edx)
28310       e9/jump $emit-subx-var-def:end/disp32
28311     }
28312     # another special-case for initializing streams
28313     # a stream is an array with 2 extra pointers
28314     {
28315       (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
28316       (is-mu-stream? %eax)  # => eax
28317       3d/compare-eax-and 0/imm32/false
28318       0f 84/jump-if-= break/disp32
28319       # var array-size-without-size/edx: int = n-12
28320       81 5/subop/subtract %edx 0xc/imm32
28321       (emit-array-data-initialization *(ebp+8) %edx)
28322       # emit read and write pointers
28323       (emit-indent *(ebp+8) *Curr-block-depth)
28324       (write-buffered *(ebp+8) "68/push 0/imm32\n")
28325       (emit-indent *(ebp+8) *Curr-block-depth)
28326       (write-buffered *(ebp+8) "68/push 0/imm32\n")
28327       #
28328       eb/jump $emit-subx-var-def:end/disp8
28329     }
28330     # while n > 0
28331     {
28332       81 7/subop/compare %edx 0/imm32
28333       7e/jump-if-<= break/disp8
28334       (emit-indent *(ebp+8) *Curr-block-depth)
28335       (write-buffered *(ebp+8) "68/push 0/imm32\n")
28336       # n -= 4
28337       81 5/subop/subtract %edx 4/imm32
28338       #
28339       eb/jump loop/disp8
28340     }
28341 $emit-subx-var-def:end:
28342     # . restore registers
28343     5a/pop-to-edx
28344     59/pop-to-ecx
28345     58/pop-to-eax
28346     # . epilogue
28347     89/<- %esp 5/r32/ebp
28348     5d/pop-to-ebp
28349     c3/return
28350 
28351 emit-array-data-initialization:  # out: (addr buffered-file), n: int
28352     # . prologue
28353     55/push-ebp
28354     89/<- %ebp 4/r32/esp
28355     #
28356     (emit-indent *(ebp+8) *Curr-block-depth)
28357     (write-buffered *(ebp+8) "(push-n-zero-bytes ")
28358     (write-int32-hex-buffered *(ebp+8) *(ebp+0xc))
28359     (write-buffered *(ebp+8) ")\n")
28360     (emit-indent *(ebp+8) *Curr-block-depth)
28361     (write-buffered *(ebp+8) "68/push ")
28362     (write-int32-hex-buffered *(ebp+8) *(ebp+0xc))
28363     (write-buffered *(ebp+8) "/imm32\n")
28364 $emit-array-data-initialization:end:
28365     # . epilogue
28366     89/<- %esp 5/r32/ebp
28367     5d/pop-to-ebp
28368     c3/return
28369 
28370 emit-subx-stmt:  # out: (addr buffered-file), stmt: (addr stmt), primitives: (addr primitive), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
28371     # . prologue
28372     55/push-ebp
28373     89/<- %ebp 4/r32/esp
28374     # . save registers
28375     50/push-eax
28376     51/push-ecx
28377     # - some special-case primitives that don't actually use the 'primitives' data structure
28378     # var op/ecx: (addr array byte) = lookup(stmt->operation)
28379     8b/-> *(ebp+0xc) 1/r32/ecx
28380     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
28381     89/<- %ecx 0/r32/eax
28382     # copy byte (can be a primitive except we need to emit a second instruction)
28383     {
28384       # if (!string-equal?(stmt->operation, "copy-byte")) break
28385       (string-equal? %ecx "copy-byte")  # => eax
28386       3d/compare-eax-and 0/imm32
28387       0f 84/jump-if-= break/disp32
28388       (translate-mu-copy-byte-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
28389       e9/jump $emit-subx-stmt:end/disp32
28390     }
28391     # copy-byte-to can be a primitive; writes to memory don't need to clear surrounding bytes
28392     # array size
28393     {
28394       # if (!string-equal?(stmt->operation, "length")) break
28395       (string-equal? %ecx "length")  # => eax
28396       3d/compare-eax-and 0/imm32
28397       0f 84/jump-if-= break/disp32
28398       (translate-mu-length-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
28399       e9/jump $emit-subx-stmt:end/disp32
28400     }
28401     # index into array
28402     {
28403       # if (!string-equal?(stmt->operation, "index")) break
28404       (string-equal? %ecx "index")  # => eax
28405       3d/compare-eax-and 0/imm32
28406       0f 84/jump-if-= break/disp32
28407       (translate-mu-index-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
28408       e9/jump $emit-subx-stmt:end/disp32
28409     }
28410     # compute-offset for index into array
28411     {
28412       # if (!string-equal?(stmt->operation, "compute-offset")) break
28413       (string-equal? %ecx "compute-offset")  # => eax
28414       3d/compare-eax-and 0/imm32
28415       0f 84/jump-if-= break/disp32
28416       (translate-mu-compute-index-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
28417       e9/jump $emit-subx-stmt:end/disp32
28418     }
28419     # get field from record
28420     {
28421       # if (!string-equal?(stmt->operation, "get")) break
28422       (string-equal? %ecx "get")  # => eax
28423       3d/compare-eax-and 0/imm32
28424       0f 84/jump-if-= break/disp32
28425       (translate-mu-get-stmt *(ebp+8) *(ebp+0xc))
28426       e9/jump $emit-subx-stmt:end/disp32
28427     }
28428     # allocate scalar
28429     {
28430       # if (!string-equal?(stmt->operation, "allocate")) break
28431       (string-equal? %ecx "allocate")  # => eax
28432       3d/compare-eax-and 0/imm32
28433       0f 84/jump-if-= break/disp32
28434       (translate-mu-allocate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
28435       e9/jump $emit-subx-stmt:end/disp32
28436     }
28437     # copy-object
28438     {
28439       # if (!string-equal?(stmt->operation, "copy-object")) break
28440       (string-equal? %ecx "copy-object")  # => eax
28441       3d/compare-eax-and 0/imm32
28442       0f 84/jump-if-= break/disp32
28443       (translate-mu-copy-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
28444       e9/jump $emit-subx-stmt:end/disp32
28445     }
28446     # clear-object
28447     {
28448       # if (!string-equal?(stmt->operation, "clear-object")) break
28449       (string-equal? %ecx "clear-object")  # => eax
28450       3d/compare-eax-and 0/imm32
28451       0f 84/jump-if-= break/disp32
28452       (translate-mu-clear-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
28453       e9/jump $emit-subx-stmt:end/disp32
28454     }
28455     # allocate array
28456     {
28457       # if (!string-equal?(stmt->operation, "populate")) break
28458       (string-equal? %ecx "populate")  # => eax
28459       3d/compare-eax-and 0/imm32
28460       0f 84/jump-if-= break/disp32
28461       (translate-mu-populate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
28462       e9/jump $emit-subx-stmt:end/disp32
28463     }
28464     # allocate stream
28465     {
28466       # if (!string-equal?(stmt->operation, "populate-stream")) break
28467       (string-equal? %ecx "populate-stream")  # => eax
28468       3d/compare-eax-and 0/imm32
28469       0f 84/jump-if-= break/disp32
28470       (translate-mu-populate-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
28471       e9/jump $emit-subx-stmt:end/disp32
28472     }
28473     # read from stream
28474     {
28475       # if (!string-equal?(stmt->operation, "read-from-stream")) break
28476       (string-equal? %ecx "read-from-stream")  # => eax
28477       3d/compare-eax-and 0/imm32
28478       0f 84/jump-if-= break/disp32
28479       (translate-mu-read-from-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
28480       e9/jump $emit-subx-stmt:end/disp32
28481     }
28482     # write to stream
28483     {
28484       # if (!string-equal?(stmt->operation, "write-to-stream")) break
28485       (string-equal? %ecx "write-to-stream")  # => eax
28486       3d/compare-eax-and 0/imm32
28487       0f 84/jump-if-= break/disp32
28488       (translate-mu-write-to-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
28489       e9/jump $emit-subx-stmt:end/disp32
28490     }
28491     # - if stmt matches a primitive, emit it
28492     {
28493 $emit-subx-stmt:check-for-primitive:
28494       # var curr/eax: (addr primitive)
28495       (find-matching-primitive *(ebp+0x10) *(ebp+0xc))  # primitives, stmt => eax
28496       3d/compare-eax-and 0/imm32
28497       74/jump-if-= break/disp8
28498 $emit-subx-stmt:primitive:
28499       (emit-subx-primitive *(ebp+8) *(ebp+0xc) %eax)  # out, stmt, curr
28500       e9/jump $emit-subx-stmt:end/disp32
28501     }
28502     # - otherwise emit a call
28503     # TODO: type-checking
28504 $emit-subx-stmt:call:
28505     (emit-call *(ebp+8) *(ebp+0xc))
28506 $emit-subx-stmt:end:
28507     # . restore registers
28508     59/pop-to-ecx
28509     58/pop-to-eax
28510     # . epilogue
28511     89/<- %esp 5/r32/ebp
28512     5d/pop-to-ebp
28513     c3/return
28514 
28515 translate-mu-length-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
28516     # . prologue
28517     55/push-ebp
28518     89/<- %ebp 4/r32/esp
28519     # . save registers
28520     50/push-eax
28521     51/push-ecx
28522     52/push-edx
28523     53/push-ebx
28524     56/push-esi
28525     # esi = stmt
28526     8b/-> *(ebp+0xc) 6/r32/esi
28527     # var base/ebx: (addr var) = stmt->inouts[0]->value
28528     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
28529     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
28530     89/<- %ebx 0/r32/eax
28531     # var elemsize/ecx: int = array-element-size(base)
28532     (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
28533     89/<- %ecx 0/r32/eax
28534     # var outreg/edx: (addr array byte) = stmt->outputs[0]->value->register
28535     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
28536     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
28537     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
28538     89/<- %edx 0/r32/eax
28539     # if elemsize == 1
28540     {
28541       81 7/subop/compare %ecx 1/imm32
28542       75/jump-if-!= break/disp8
28543 $translate-mu-length-stmt:size-1:
28544       (emit-save-size-to *(ebp+8) %ebx %edx)
28545       e9/jump $translate-mu-length-stmt:end/disp32
28546     }
28547     # if elemsize is a power of 2 less than 256
28548     {
28549       (power-of-2? %ecx *(ebp+0x10) *(ebp+0x14))  # => eax
28550       3d/compare-eax-and 0/imm32/false
28551       74/jump-if-= break/disp8
28552       81 7/subop/compare %ecx 0xff/imm32
28553       7f/jump-if-> break/disp8
28554 $translate-mu-length-stmt:size-power-of-2:
28555       (emit-save-size-to *(ebp+8) %ebx %edx)
28556       (emit-divide-by-shift-right *(ebp+8) %edx %ecx)
28557       e9/jump $translate-mu-length-stmt:end/disp32
28558     }
28559     # otherwise, the complex case
28560     # . emit register spills
28561     {
28562 $translate-mu-length-stmt:complex:
28563       (string-equal? %edx "eax")  # => eax
28564       3d/compare-eax-and 0/imm32/false
28565       75/break-if-!= break/disp8
28566       (emit-indent *(ebp+8) *Curr-block-depth)
28567       (write-buffered *(ebp+8) "50/push-eax\n")
28568     }
28569     {
28570       (string-equal? %edx "ecx")  # => eax
28571       3d/compare-eax-and 0/imm32/false
28572       75/break-if-!= break/disp8
28573       (emit-indent *(ebp+8) *Curr-block-depth)
28574       (write-buffered *(ebp+8) "51/push-ecx\n")
28575     }
28576     {
28577       (string-equal? %edx "edx")  # => eax
28578       3d/compare-eax-and 0/imm32/false
28579       75/break-if-!= break/disp8
28580       (emit-indent *(ebp+8) *Curr-block-depth)
28581       (write-buffered *(ebp+8) "52/push-edx\n")
28582     }
28583     # .
28584     (emit-save-size-to *(ebp+8) %ebx "eax")
28585     (emit-indent *(ebp+8) *Curr-block-depth)
28586     (write-buffered *(ebp+8) "31/xor %edx 2/r32/edx\n")
28587     (emit-indent *(ebp+8) *Curr-block-depth)
28588     (write-buffered *(ebp+8) "b9/copy-to-ecx ")
28589     (write-int32-hex-buffered *(ebp+8) %ecx)
28590     (write-buffered *(ebp+8) "/imm32\n")
28591     (emit-indent *(ebp+8) *Curr-block-depth)
28592     (write-buffered *(ebp+8) "f7 7/subop/idiv-eax-edx-by %ecx\n")
28593     {
28594       (string-equal? %edx "eax")  # => eax
28595       3d/compare-eax-and 0/imm32/false
28596       75/break-if-!= break/disp8
28597       (emit-indent *(ebp+8) *Curr-block-depth)
28598       (write-buffered *(ebp+8) "89/<- %")
28599       (write-buffered *(ebp+8) %edx)
28600       (write-buffered *(ebp+8) " 0/r32/eax\n")
28601     }
28602     # . emit register restores
28603     {
28604       (string-equal? %edx "edx")  # => eax
28605       3d/compare-eax-and 0/imm32/false
28606       75/break-if-!= break/disp8
28607       (emit-indent *(ebp+8) *Curr-block-depth)
28608       (write-buffered *(ebp+8) "5a/pop-to-edx\n")
28609     }
28610     {
28611       (string-equal? %edx "ecx")  # => eax
28612       3d/compare-eax-and 0/imm32/false
28613       75/break-if-!= break/disp8
28614       (emit-indent *(ebp+8) *Curr-block-depth)
28615       (write-buffered *(ebp+8) "59/pop-to-ecx\n")
28616     }
28617     {
28618       (string-equal? %edx "eax")  # => eax
28619       3d/compare-eax-and 0/imm32/false
28620       75/break-if-!= break/disp8
28621       (emit-indent *(ebp+8) *Curr-block-depth)
28622       (write-buffered *(ebp+8) "58/pop-to-eax\n")
28623     }
28624 $translate-mu-length-stmt:end:
28625     # . restore registers
28626     5e/pop-to-esi
28627     5b/pop-to-ebx
28628     5a/pop-to-edx
28629     59/pop-to-ecx
28630     58/pop-to-eax
28631     # . epilogue
28632     89/<- %esp 5/r32/ebp
28633     5d/pop-to-ebp
28634     c3/return
28635 
28636 array-element-size:  # arr: (addr var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
28637     # . prologue
28638     55/push-ebp
28639     89/<- %ebp 4/r32/esp
28640     #
28641     (array-element-type-id *(ebp+8) *(ebp+0xc) *(ebp+0x10))  # => eax
28642     (size-of-type-id-as-array-element %eax)  # => eax
28643 $array-element-size:end:
28644     # . epilogue
28645     89/<- %esp 5/r32/ebp
28646     5d/pop-to-ebp
28647     c3/return
28648 
28649 array-element-type-id:  # v: (addr var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: type-id
28650     # precondition: n is positive
28651     # . prologue
28652     55/push-ebp
28653     89/<- %ebp 4/r32/esp
28654     #
28655     8b/-> *(ebp+8) 0/r32/eax
28656     # var t/eax: (addr type-tree)
28657     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
28658     # if t == 0 abort
28659     3d/compare-eax-with 0/imm32
28660     0f 84/jump-if-== $array-element-type-id:error0/disp32
28661     # if t->is-atom? abort
28662     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
28663     0f 85/jump-if-!= $array-element-type-id:error1/disp32
28664     # if (t->left == addr) t = t->right
28665     {
28666       50/push-eax
28667       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
28668       (is-simple-mu-type? %eax 2)  # addr => eax
28669       3d/compare-eax-with 0/imm32/false
28670       58/pop-to-eax
28671       74/jump-if-= break/disp8
28672 $array-element-type-id:skip-addr:
28673       (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
28674     }
28675     # if t == 0 abort
28676     3d/compare-eax-with 0/imm32
28677     0f 84/jump-if-= $array-element-type-id:error2/disp32
28678     # if t->is-atom? abort
28679     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
28680     0f 85/jump-if-!= $array-element-type-id:error2/disp32
28681     # if t->left != array abort
28682     {
28683       50/push-eax
28684       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
28685       (is-simple-mu-type? %eax 3)  # array => eax
28686       3d/compare-eax-with 0/imm32/false
28687       58/pop-to-eax
28688 $array-element-type-id:no-array:
28689       0f 84/jump-if-= $array-element-type-id:error2/disp32
28690     }
28691 $array-element-type-id:skip-array:
28692     # t = t->right
28693     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
28694     # if t == 0 abort
28695     3d/compare-eax-with 0/imm32
28696     0f 84/jump-if-= $array-element-type-id:error2/disp32
28697     # if t->is-atom? abort
28698     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
28699     0f 85/jump-if-!= $array-element-type-id:error2/disp32
28700     # t = t->left
28701     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
28702     # if (!t->is-atom?) t = t->left     # TODO: assumes array element size can be determined from just first word of array element type
28703     # if (t->is-atom == false) t = lookup(t->left)
28704     {
28705       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
28706       75/jump-if-!= break/disp8
28707       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
28708     }
28709     # return t->value
28710     8b/-> *(eax+4) 0/r32/eax  # Type-tree-value
28711 $array-element-type-id:end:
28712     # . epilogue
28713     89/<- %esp 5/r32/ebp
28714     5d/pop-to-ebp
28715     c3/return
28716 
28717 $array-element-type-id:error0:
28718     (write-buffered *(ebp+0xc) "array-element-type-id: var '")
28719     50/push-eax
28720     8b/-> *(ebp+8) 0/r32/eax
28721     (lookup *eax *(eax+4))  # Var-name Var-name => eax
28722     (write-buffered *(ebp+0xc) %eax)
28723     58/pop-to-eax
28724     (write-buffered *(ebp+0xc) "' has no type\n")
28725     (flush *(ebp+0xc))
28726     (stop *(ebp+0x10) 1)
28727     # never gets here
28728 
28729 $array-element-type-id:error1:
28730     (write-buffered *(ebp+0xc) "array-element-type-id: var '")
28731     50/push-eax
28732     8b/-> *(ebp+8) 0/r32/eax
28733     (lookup *eax *(eax+4))  # Var-name Var-name => eax
28734     (write-buffered *(ebp+0xc) %eax)
28735     58/pop-to-eax
28736     (write-buffered *(ebp+0xc) "' has atomic type ")
28737     (write-int32-hex-buffered *(ebp+0xc) *(eax+4))  # Type-tree-value
28738     (write-buffered *(ebp+0xc) Newline)
28739     (flush *(ebp+0xc))
28740     (stop *(ebp+0x10) 1)
28741     # never gets here
28742 
28743 $array-element-type-id:error2:
28744     (write-buffered *(ebp+0xc) "array-element-type-id: var '")
28745     50/push-eax
28746     8b/-> *(ebp+8) 0/r32/eax
28747     (lookup *eax *(eax+4))  # Var-name Var-name => eax
28748     (write-buffered *(ebp+0xc) %eax)
28749     58/pop-to-eax
28750     (write-buffered *(ebp+0xc) "' has non-array type\n")
28751     (flush *(ebp+0xc))
28752     (stop *(ebp+0x10) 1)
28753     # never gets here
28754 
28755 size-of-type-id-as-array-element:  # t: type-id -> result/eax: int
28756     # . prologue
28757     55/push-ebp
28758     89/<- %ebp 4/r32/esp
28759     # eax = t
28760     8b/-> *(ebp+8) 0/r32/eax
28761     # if t is 'byte', size is 1
28762     3d/compare-eax-and 8/imm32/byte
28763     {
28764       75/jump-if-!= break/disp8
28765       b8/copy-to-eax 1/imm32
28766       eb/jump $size-of-type-id-as-array-element:end/disp8
28767     }
28768     # otherwise proceed as usual
28769     (size-of-type-id %eax)  # => eax
28770 $size-of-type-id-as-array-element:end:
28771     # . epilogue
28772     89/<- %esp 5/r32/ebp
28773     5d/pop-to-ebp
28774     c3/return
28775 
28776 emit-save-size-to:  # out: (addr buffered-file), base: (addr var), outreg: (addr array byte)
28777     # . prologue
28778     55/push-ebp
28779     89/<- %ebp 4/r32/esp
28780     # . save registers
28781     50/push-eax
28782     53/push-ebx
28783     # ebx = base
28784     8b/-> *(ebp+0xc) 3/r32/ebx
28785     (emit-indent *(ebp+8) *Curr-block-depth)
28786     (write-buffered *(ebp+8) "8b/-> *")
28787     # if base is an (addr array ...) in a register
28788     {
28789       81 7/subop/compare *(ebx+0x18)) 0/imm32  # Var-register
28790       74/jump-if-= break/disp8
28791 $emit-save-size-to:emit-base-from-register:
28792       (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
28793       (write-buffered *(ebp+8) %eax)
28794       eb/jump $emit-save-size-to:emit-output/disp8
28795     }
28796     # otherwise if base is an (array ...) on the stack
28797     {
28798       81 7/subop/compare *(ebx+0x14)) 0/imm32  # Var-offset
28799       74/jump-if-= break/disp8
28800 $emit-save-size-to:emit-base-from-stack:
28801       (write-buffered *(ebp+8) "(ebp+")
28802       (write-int32-hex-buffered *(ebp+8) *(ebx+0x14))  # Var-offset
28803       (write-buffered *(ebp+8) ")")
28804     }
28805 $emit-save-size-to:emit-output:
28806     (write-buffered *(ebp+8) " ")
28807     (get Mu-registers *(ebp+0x10) 0xc "Mu-registers")  # => eax
28808     (write-int32-hex-buffered *(ebp+8) *eax)
28809     (write-buffered *(ebp+8) "/r32\n")
28810 $emit-save-size-to:end:
28811     # . restore registers
28812     5b/pop-to-ebx
28813     58/pop-to-eax
28814     # . epilogue
28815     89/<- %esp 5/r32/ebp
28816     5d/pop-to-ebp
28817     c3/return
28818 
28819 emit-divide-by-shift-right:  # out: (addr buffered-file), reg: (addr array byte), size: int
28820     # . prologue
28821     55/push-ebp
28822     89/<- %ebp 4/r32/esp
28823     # . save registers
28824     50/push-eax
28825     #
28826     (emit-indent *(ebp+8) *Curr-block-depth)
28827     (write-buffered *(ebp+8) "c1/shift 5/subop/>> %")
28828     (write-buffered *(ebp+8) *(ebp+0xc))
28829     (write-buffered *(ebp+8) Space)
28830     (num-shift-rights *(ebp+0x10))  # => eax
28831     (write-int32-hex-buffered *(ebp+8) %eax)
28832     (write-buffered *(ebp+8) "/imm8\n")
28833 $emit-divide-by-shift-right:end:
28834     # . restore registers
28835     58/pop-to-eax
28836     # . epilogue
28837     89/<- %esp 5/r32/ebp
28838     5d/pop-to-ebp
28839     c3/return
28840 
28841 translate-mu-copy-byte-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
28842     # . prologue
28843     55/push-ebp
28844     89/<- %ebp 4/r32/esp
28845     # . save registers
28846     50/push-eax
28847     56/push-esi
28848     # esi = stmt
28849     8b/-> *(ebp+0xc) 6/r32/esi
28850     #
28851     (emit-indent *(ebp+8) *Curr-block-depth)
28852     (write-buffered *(ebp+8) "8a/byte->")
28853     # emit stmt->inouts[0]
28854     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
28855     (emit-subx-var-as-rm32 *(ebp+8) %eax)
28856     # emit /r32 for stmt->outputs[0]->register
28857     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
28858     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
28859     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
28860     (maybe-get Mu-registers %eax 0xc)  # => eax: (addr register-index)
28861     (write-buffered *(ebp+8) Space)
28862     (write-int32-hex-buffered *(ebp+8) *eax)
28863     (write-buffered *(ebp+8) "/r32\n")
28864     # clear rest of register
28865     (emit-indent *(ebp+8) *Curr-block-depth)
28866     (write-buffered *(ebp+8) "81 4/subop/and %")
28867     8b/-> *(ebp+0xc) 0/r32/eax
28868     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
28869     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
28870     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
28871     (write-buffered *(ebp+8) %eax)
28872     (write-buffered *(ebp+8) " 0xff/imm32\n")
28873 $translate-mu-copy-byte-stmt:end:
28874     # . restore registers
28875     5e/pop-to-esi
28876     58/pop-to-eax
28877     # . epilogue
28878     89/<- %esp 5/r32/ebp
28879     5d/pop-to-ebp
28880     c3/return
28881 
28882 # a little different from other translate- functions; notice the extra 'fn' argument
28883 translate-mu-index-stmt:  # out: (addr buffered-file), stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
28884     # . prologue
28885     55/push-ebp
28886     89/<- %ebp 4/r32/esp
28887     # . save registers
28888     53/push-ebx
28889     # ebx = stmt
28890     8b/-> *(ebp+0xc) 3/r32/ebx
28891     # var base/ebx: (addr var) = stmt->inouts[0]
28892     (lookup *(ebx+0xc) *(ebx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
28893     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
28894     89/<- %ebx 0/r32/eax
28895     # emit bounds-check
28896     (emit-mu-index-bounds-check *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18))
28897     # if (var->register) do one thing
28898     {
28899       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
28900       74/jump-if-= break/disp8
28901       # TODO: ensure there's no dereference
28902       (translate-mu-index-stmt-with-array-in-register *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
28903       eb/jump $translate-mu-index-stmt:end/disp8
28904     }
28905     # if (var->offset) do a different thing
28906     {
28907       81 7/subop/compare *(ebx+0x14) 0/imm32  # Var-offset
28908       74/jump-if-= break/disp8
28909       # TODO: ensure there's no dereference
28910       (translate-mu-index-stmt-with-array-on-stack *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
28911       eb/jump $translate-mu-index-stmt:end/disp8
28912     }
28913 $translate-mu-index-stmt:end:
28914     # . restore registers
28915     5b/pop-to-ebx
28916     # . epilogue
28917     89/<- %esp 5/r32/ebp
28918     5d/pop-to-ebp
28919     c3/return
28920 
28921 $translate-mu-index-stmt:error1:
28922     (write-buffered *(ebp+0x14) "couldn't translate an index instruction. second (index) input must either lie in a register or be a literal\n")
28923     (flush *(ebp+0x14))
28924     (stop *(ebp+0x18) 1)
28925     # never gets here
28926 
28927 $translate-mu-index-stmt:error2:
28928     (write-buffered *(ebp+0x14) "couldn't translate an index instruction. second (index) input when in a register must be an int or offset\n")
28929     (flush *(ebp+0x14))
28930     (stop *(ebp+0x18) 1)
28931     # never gets here
28932 
28933 emit-mu-index-bounds-check:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
28934     # . prologue
28935     55/push-ebp
28936     89/<- %ebp 4/r32/esp
28937     # . save registers
28938     50/push-eax
28939     51/push-ecx
28940     52/push-edx
28941     53/push-ebx
28942     # ecx = stmt
28943     8b/-> *(ebp+0xc) 1/r32/ecx
28944     #
28945     (emit-indent *(ebp+8) *Curr-block-depth)
28946     (write-buffered *(ebp+8) "(__check-mu-array-bounds ")
28947 $emit-mu-index-bounds-check:compute-base:
28948     # var base/ebx: (addr var) = inouts[0]
28949     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
28950     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
28951     89/<- %ebx 0/r32/eax
28952 $emit-mu-index-bounds-check:emit-index:
28953     # var index/edx: (addr var) = inouts[1]
28954     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
28955     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
28956     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
28957     89/<- %edx 0/r32/eax
28958     # if index->register, print its code
28959     81 7/subop/compare *(edx+0x18) 0/imm32  # Var-register
28960     {
28961       0f 84/jump-if-= break/disp32
28962 $emit-mu-index-bounds-check:emit-register-index:
28963       (write-buffered *(ebp+8) "%")
28964       (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
28965       (write-buffered *(ebp+8) %eax)
28966       eb/jump $emit-mu-index-bounds-check:index-done/disp8
28967     }
28968     # otherwise if index is a literal, print it
28969 $emit-mu-index-bounds-check:emit-literal-index:
28970     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
28971     (is-simple-mu-type? %eax 0)  # => eax
28972     3d/compare-eax-and 0/imm32/false
28973     {
28974       0f 84/jump-if-= break/disp32
28975       (lookup *edx *(edx+4))  # Var-name Var-name => eax
28976       (write-buffered *(ebp+8) %eax)
28977     }
28978 $emit-mu-index-bounds-check:index-done:
28979     (write-buffered *(ebp+8) " ")
28980 $emit-mu-index-bounds-check:emit-element-size:
28981     # if index is a literal or int, print size of array element
28982     {
28983       {
28984         (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
28985         (is-simple-mu-type? %eax 0)  # literal => eax
28986         3d/compare-eax-and 0/imm32/false
28987         75/jump-if-!= break/disp8
28988         (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
28989         (is-simple-mu-type? %eax 1)  # int => eax
28990         3d/compare-eax-and 0/imm32/false
28991         75/jump-if-!= break/disp8
28992         eb/jump $emit-mu-index-bounds-check:emit-element-size-offset/disp8
28993       }
28994 $emit-mu-index-bounds-check:emit-int-register-index:
28995       (array-element-size %ebx *(ebp+0x14) *(ebp+0x18))  # => eax
28996       (write-int32-hex-buffered *(ebp+8) %eax)
28997       e9/jump $emit-mu-index-bounds-check:emit-base/disp32
28998     }
28999 $emit-mu-index-bounds-check:emit-element-size-offset:
29000     # if index has type (offset ...), print "1"
29001     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
29002     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
29003     {
29004       75/jump-if-!= break/disp8
29005       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
29006       (is-simple-mu-type? %eax 7)  # => eax
29007       3d/compare-eax-and 0/imm32/false
29008       {
29009         0f 84/jump-if-= break/disp32
29010 $emit-mu-index-bounds-check:emit-offset-register-index:
29011         (write-buffered *(ebp+8) "1")
29012       }
29013     }
29014 $emit-mu-index-bounds-check:emit-base:
29015     # if base is in a register, print " *" base->register
29016     81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
29017     {
29018       74/jump-if-= break/disp8
29019       (write-buffered *(ebp+8) " *")
29020       (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
29021       (write-buffered *(ebp+8) %eax)
29022       e9/jump $emit-mu-index-bounds-check:emit-function-name/disp32
29023     }
29024     # otherwise print " *(ebp+" base->offset ")"
29025     (write-buffered *(ebp+8) " *(ebp+")
29026     (write-int32-hex-buffered *(ebp+8) *(ebx+0x14))  # Var-offset
29027     (write-buffered *(ebp+8) ")")
29028 $emit-mu-index-bounds-check:emit-function-name:
29029     # " \"" function-name "\""
29030     (write-buffered *(ebp+8) " \"")
29031     8b/-> *(ebp+0x10) 1/r32/ecx
29032     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
29033     (write-buffered *(ebp+8) %eax)
29034     (write-buffered *(ebp+8) "\"")
29035 $emit-mu-index-bounds-check:emit-array-name:
29036     # " \"" base->name "\""
29037     (write-buffered *(ebp+8) " \"")
29038     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
29039     (write-buffered *(ebp+8) %eax)
29040     (write-buffered *(ebp+8) "\")\n")
29041 $emit-mu-index-bounds-check:end:
29042     # . restore registers
29043     5b/pop-to-ebx
29044     5a/pop-to-edx
29045     59/pop-to-ecx
29046     58/pop-to-eax
29047     # . epilogue
29048     89/<- %esp 5/r32/ebp
29049     5d/pop-to-ebp
29050     c3/return
29051 
29052 translate-mu-index-stmt-with-array-in-register:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
29053     # . prologue
29054     55/push-ebp
29055     89/<- %ebp 4/r32/esp
29056     # . save registers
29057     50/push-eax
29058     51/push-ecx
29059     52/push-edx
29060     53/push-ebx
29061     #
29062     (emit-indent *(ebp+8) *Curr-block-depth)
29063     (write-buffered *(ebp+8) "8d/copy-address *(")
29064     # TODO: ensure inouts[0] is in a register and not dereferenced
29065 $translate-mu-index-stmt-with-array-in-register:emit-base:
29066     # ecx = stmt
29067     8b/-> *(ebp+0xc) 1/r32/ecx
29068     # var base/ebx: (addr var) = inouts[0]
29069     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29070     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29071     89/<- %ebx 0/r32/eax
29072     # print base->register " + "
29073     (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
29074     (write-buffered *(ebp+8) %eax)
29075     (write-buffered *(ebp+8) " + ")
29076     # var index/edx: (addr var) = inouts[1]
29077     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29078     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
29079     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29080     89/<- %edx 0/r32/eax
29081     # if index->register
29082     81 7/subop/compare *(edx+0x18) 0/imm32  # Var-register
29083     {
29084       0f 84/jump-if-= break/disp32
29085 $translate-mu-index-stmt-with-array-in-register:emit-register-index:
29086       # if index is an int
29087       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
29088       (is-simple-mu-type? %eax 1)  # int => eax
29089       3d/compare-eax-and 0/imm32/false
29090       {
29091         0f 84/jump-if-= break/disp32
29092 $translate-mu-index-stmt-with-array-in-register:emit-int-register-index:
29093         # print index->register "<<" log2(array-element-size(base)) " + 4) "
29094         # . index->register "<<"
29095         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
29096         (write-buffered *(ebp+8) %eax)
29097         (write-buffered *(ebp+8) "<<")
29098         # . log2(array-element-size(base->type))
29099         # we know size is a power of 2
29100         (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
29101         (num-shift-rights %eax)  # => eax
29102         (write-int32-hex-buffered *(ebp+8) %eax)
29103         e9/jump $translate-mu-index-stmt-with-array-in-register:emit-register-index-done/disp32
29104       }
29105       # if index->type is any other atom, abort
29106       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
29107       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
29108       0f 85/jump-if-!= $translate-mu-index-stmt:error2/disp32
29109       # if index has type (offset ...)
29110       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
29111       (is-simple-mu-type? %eax 7)  # => eax
29112       3d/compare-eax-and 0/imm32/false
29113       {
29114         0f 84/jump-if-= break/disp32
29115         # print index->register
29116 $translate-mu-index-stmt-with-array-in-register:emit-offset-register-index:
29117         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
29118         (write-buffered *(ebp+8) %eax)
29119       }
29120 $translate-mu-index-stmt-with-array-in-register:emit-register-index-done:
29121       (write-buffered *(ebp+8) " + 4) ")
29122       e9/jump $translate-mu-index-stmt-with-array-in-register:emit-output/disp32
29123     }
29124     # otherwise if index is a literal
29125     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
29126     (is-simple-mu-type? %eax 0)  # => eax
29127     3d/compare-eax-and 0/imm32/false
29128     {
29129       0f 84/jump-if-= break/disp32
29130 $translate-mu-index-stmt-with-array-in-register:emit-literal-index:
29131       # var index-value/edx: int = parse-hex-int(index->name)
29132       (lookup *edx *(edx+4))  # Var-name Var-name => eax
29133       (parse-hex-int %eax)  # => eax
29134       89/<- %edx 0/r32/eax
29135       # offset = idx-value * array-element-size(base->type)
29136       (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
29137       f7 4/subop/multiply-into-edx-eax %edx  # clobbers edx
29138       # offset += 4 for array size
29139       05/add-to-eax 4/imm32
29140       # TODO: check edx for overflow
29141       # print offset
29142       (write-int32-hex-buffered *(ebp+8) %eax)
29143       (write-buffered *(ebp+8) ") ")
29144       e9/jump $translate-mu-index-stmt-with-array-in-register:emit-output/disp32
29145     }
29146     # otherwise abort
29147     e9/jump $translate-mu-index-stmt:error1/disp32
29148 $translate-mu-index-stmt-with-array-in-register:emit-output:
29149     # outputs[0] "/r32"
29150     8b/-> *(ebp+0xc) 1/r32/ecx
29151     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
29152     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29153     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
29154     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
29155     (write-int32-hex-buffered *(ebp+8) *eax)
29156     (write-buffered *(ebp+8) "/r32\n")
29157 $translate-mu-index-stmt-with-array-in-register:end:
29158     # . restore registers
29159     5b/pop-to-ebx
29160     5a/pop-to-edx
29161     59/pop-to-ecx
29162     58/pop-to-eax
29163     # . epilogue
29164     89/<- %esp 5/r32/ebp
29165     5d/pop-to-ebp
29166     c3/return
29167 
29168 translate-mu-index-stmt-with-array-on-stack:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
29169     # . prologue
29170     55/push-ebp
29171     89/<- %ebp 4/r32/esp
29172     # . save registers
29173     50/push-eax
29174     51/push-ecx
29175     52/push-edx
29176     53/push-ebx
29177     #
29178     (emit-indent *(ebp+8) *Curr-block-depth)
29179     (write-buffered *(ebp+8) "8d/copy-address *(ebp + ")
29180     # var curr/edx: (addr stmt-var) = lookup(stmt->inouts)
29181     8b/-> *(ebp+0xc) 0/r32/eax
29182     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29183     89/<- %edx 0/r32/eax
29184     # var base/ecx: (addr var) = lookup(curr->value)
29185     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29186     89/<- %ecx 0/r32/eax
29187     # var curr2/eax: (addr stmt-var) = lookup(curr->next)
29188     (lookup *(edx+8) *(edx+0xc))  # Stmt-var-next Stmt-var-next => eax
29189     # var index/edx: (handle var) = curr2->value
29190     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29191     89/<- %edx 0/r32/eax
29192     # if index->register
29193     81 7/subop/compare *(edx+0x18) 0/imm32  # Var-register
29194     {
29195       0f 84/jump-if-= break/disp32
29196 $translate-mu-index-stmt-with-array-on-stack:emit-register-index:
29197       # if index is an int
29198       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
29199       (is-simple-mu-type? %eax 1)  # int => eax
29200       3d/compare-eax-and 0/imm32/false
29201       {
29202         0f 84/jump-if-= break/disp32
29203 $translate-mu-index-stmt-with-array-on-stack:emit-int-register-index:
29204         # print index->register "<<" log2(array-element-size(base)) " + " base->offset+4
29205         # . inouts[1]->register "<<"
29206         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
29207         (write-buffered *(ebp+8) %eax)
29208         (write-buffered *(ebp+8) "<<")
29209         # . log2(array-element-size(base))
29210         # TODO: ensure size is a power of 2
29211         (array-element-size %ecx *(ebp+0x10) *(ebp+0x14))  # => eax
29212         (num-shift-rights %eax)  # => eax
29213         (write-int32-hex-buffered *(ebp+8) %eax)
29214         #
29215         (write-buffered *(ebp+8) " + ")
29216         #
29217         8b/-> *(ecx+0x14) 0/r32/eax  # Var-offset
29218         05/add-to-eax 4/imm32  # for array length
29219         (write-int32-hex-buffered *(ebp+8) %eax)
29220         e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-register-index-done/disp32
29221       }
29222       # if index->type is any other atom, abort
29223       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
29224       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
29225       0f 85/jump-if-!= $translate-mu-index-stmt:error2/disp32
29226       # if index has type (offset ...)
29227       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
29228       (is-simple-mu-type? %eax 7)  # => eax
29229       3d/compare-eax-and 0/imm32/false
29230       {
29231         0f 84/jump-if-= break/disp32
29232         # print index->register
29233 $translate-mu-index-stmt-with-array-on-stack:emit-offset-register-index:
29234         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
29235         (write-buffered *(ebp+8) %eax)
29236       }
29237 $translate-mu-index-stmt-with-array-on-stack:emit-register-index-done:
29238       (write-buffered *(ebp+8) ") ")
29239       e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-output/disp32
29240     }
29241     # otherwise if index is a literal
29242     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
29243     (is-simple-mu-type? %eax 0)  # => eax
29244     3d/compare-eax-and 0/imm32/false
29245     {
29246       0f 84/jump-if-= break/disp32
29247 $translate-mu-index-stmt-with-array-on-stack:emit-literal-index:
29248       # var idx-value/edx: int = parse-hex-int(index->name)
29249       (lookup *edx *(edx+4))  # Var-name Var-name => eax
29250       (parse-hex-int %eax)  # Var-name => eax
29251       89/<- %edx 0/r32/eax
29252       # offset = idx-value * array-element-size(base)
29253       (array-element-size %ecx *(ebp+0x10) *(ebp+0x14))  # => eax
29254       f7 4/subop/multiply-into-edx-eax %edx  # clobbers edx
29255       # offset += base->offset
29256       03/add *(ecx+0x14) 0/r32/eax  # Var-offset
29257       # offset += 4 for array size
29258       05/add-to-eax 4/imm32
29259       # TODO: check edx for overflow
29260       # print offset
29261       (write-int32-hex-buffered *(ebp+8) %eax)
29262       (write-buffered *(ebp+8) ") ")
29263       e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-output/disp32
29264     }
29265     # otherwise abort
29266     e9/jump $translate-mu-index-stmt:error1/disp32
29267 $translate-mu-index-stmt-with-array-on-stack:emit-output:
29268     # outputs[0] "/r32"
29269     8b/-> *(ebp+0xc) 0/r32/eax
29270     (lookup *(eax+0x14) *(eax+0x18))  # Stmt1-outputs Stmt1-outputs => eax
29271     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29272     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
29273     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
29274     (write-int32-hex-buffered *(ebp+8) *eax)
29275     (write-buffered *(ebp+8) "/r32\n")
29276 $translate-mu-index-stmt-with-array-on-stack:end:
29277     # . restore registers
29278     5b/pop-to-ebx
29279     5a/pop-to-edx
29280     59/pop-to-ecx
29281     58/pop-to-eax
29282     # . epilogue
29283     89/<- %esp 5/r32/ebp
29284     5d/pop-to-ebp
29285     c3/return
29286 
29287 translate-mu-compute-index-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
29288     # . prologue
29289     55/push-ebp
29290     89/<- %ebp 4/r32/esp
29291     # . save registers
29292     50/push-eax
29293     51/push-ecx
29294     52/push-edx
29295     53/push-ebx
29296     #
29297     (emit-indent *(ebp+8) *Curr-block-depth)
29298     (write-buffered *(ebp+8) "69/multiply")
29299     # ecx = stmt
29300     8b/-> *(ebp+0xc) 1/r32/ecx
29301     # var first-inout/ebx: (addr stmt-var) = stmt->inouts[0]
29302     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29303     89/<- %ebx 0/r32/eax
29304 $translate-mu-compute-index-stmt:emit-index:
29305     (lookup *(ebx+8) *(ebx+0xc))  # Stmt-var-next Stmt-var-next => eax
29306     (emit-subx-var-as-rm32 *(ebp+8) %eax)
29307     (write-buffered *(ebp+8) Space)
29308 $translate-mu-compute-index-stmt:emit-elem-size:
29309     # var base/ebx: (addr var)
29310     (lookup *ebx *(ebx+4))  # Stmt-var-value Stmt-var-value => eax
29311     89/<- %ebx 0/r32/eax
29312     # print array-element-size(base)
29313     (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
29314     (write-int32-hex-buffered *(ebp+8) %eax)
29315     (write-buffered *(ebp+8) "/imm32 ")
29316 $translate-mu-compute-index-stmt:emit-output:
29317     # outputs[0] "/r32"
29318     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
29319     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29320     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
29321     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
29322     (write-int32-hex-buffered *(ebp+8) *eax)
29323     (write-buffered *(ebp+8) "/r32\n")
29324 $translate-mu-compute-index-stmt:end:
29325     # . restore registers
29326     5b/pop-to-ebx
29327     5a/pop-to-edx
29328     59/pop-to-ecx
29329     58/pop-to-eax
29330     # . epilogue
29331     89/<- %esp 5/r32/ebp
29332     5d/pop-to-ebp
29333     c3/return
29334 
29335 translate-mu-get-stmt:  # out: (addr buffered-file), stmt: (addr stmt)
29336     # . prologue
29337     55/push-ebp
29338     89/<- %ebp 4/r32/esp
29339     # . save registers
29340     50/push-eax
29341     51/push-ecx
29342     52/push-edx
29343     #
29344     (emit-indent *(ebp+8) *Curr-block-depth)
29345     (write-buffered *(ebp+8) "8d/copy-address ")
29346     # ecx = stmt
29347     8b/-> *(ebp+0xc) 1/r32/ecx
29348     # var offset/edx: int = get offset of stmt
29349     (mu-get-offset %ecx)  # => eax
29350     89/<- %edx 0/r32/eax
29351     # var base/eax: (addr var) = stmt->inouts->value
29352     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29353     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29354     # if base is in a register
29355     81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
29356     {
29357       0f 84/jump-if-= break/disp32
29358 $translate-mu-get-stmt:emit-register-input:
29359       # emit "*(" base->register " + " offset ") "
29360       (write-buffered *(ebp+8) "*(")
29361       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
29362       (write-buffered *(ebp+8) %eax)
29363       (write-buffered *(ebp+8) " + ")
29364       (write-int32-hex-buffered *(ebp+8) %edx)
29365       (write-buffered *(ebp+8) ") ")
29366       e9/jump $translate-mu-get-stmt:emit-output/disp32
29367     }
29368     # otherwise base is on the stack
29369     {
29370 $translate-mu-get-stmt:emit-stack-input:
29371       # emit "*(ebp + " inouts[0]->stack-offset + offset ") "
29372       (write-buffered *(ebp+8) "*(ebp+")
29373       03/add *(eax+0x14) 2/r32/edx  # Var-offset
29374       (write-int32-hex-buffered *(ebp+8) %edx)
29375       (write-buffered *(ebp+8) ") ")
29376       eb/jump $translate-mu-get-stmt:emit-output/disp8
29377     }
29378 $translate-mu-get-stmt:emit-output:
29379     # var output/eax: (addr var) = stmt->outputs->value
29380     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
29381     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29382     # emit offset->register "/r32"
29383     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
29384     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
29385     (write-int32-hex-buffered *(ebp+8) *eax)
29386     (write-buffered *(ebp+8) "/r32\n")
29387 $translate-mu-get-stmt:end:
29388     # . restore registers
29389     5a/pop-to-edx
29390     59/pop-to-ecx
29391     58/pop-to-eax
29392     # . epilogue
29393     89/<- %esp 5/r32/ebp
29394     5d/pop-to-ebp
29395     c3/return
29396 
29397 translate-mu-copy-object-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
29398     # . prologue
29399     55/push-ebp
29400     89/<- %ebp 4/r32/esp
29401     # . save registers
29402     50/push-eax
29403     #
29404     (emit-indent *(ebp+8) *Curr-block-depth)
29405     (write-buffered *(ebp+8) "(copy-bytes")
29406     # eax = stmt
29407     8b/-> *(ebp+0xc) 0/r32/eax
29408     # var first-inout/eax: (addr stmt-var) = stmt->inouts[0]
29409     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29410     (emit-subx-call-operand *(ebp+8) %eax)
29411     # var second-inout/eax: (addr stmt-var) = stmt->inouts[1]
29412     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
29413     (emit-subx-call-operand *(ebp+8) %eax)
29414     # emit size of inouts
29415     (write-buffered *(ebp+8) Space)
29416     (addr-payload-size %eax *(ebp+0x10) *(ebp+0x14))  # => eax
29417     (write-int32-hex-buffered *(ebp+8) %eax)
29418     (write-buffered *(ebp+8) ")\n")
29419 $translate-mu-copy-object-stmt:end:
29420     # . restore registers
29421     58/pop-to-eax
29422     # . epilogue
29423     89/<- %esp 5/r32/ebp
29424     5d/pop-to-ebp
29425     c3/return
29426 
29427 translate-mu-clear-object-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
29428     # . prologue
29429     55/push-ebp
29430     89/<- %ebp 4/r32/esp
29431     # . save registers
29432     50/push-eax
29433     #
29434     (emit-indent *(ebp+8) *Curr-block-depth)
29435     (write-buffered *(ebp+8) "(zero-out")
29436     # eax = stmt
29437     8b/-> *(ebp+0xc) 0/r32/eax
29438     # var dest/eax: (addr stmt-var) = stmt->inouts[0]
29439     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29440     #
29441     (emit-subx-call-operand *(ebp+8) %eax)
29442     (write-buffered *(ebp+8) Space)
29443     (addr-payload-size %eax *(ebp+0x10) *(ebp+0x14))  # => eax
29444     (write-int32-hex-buffered *(ebp+8) %eax)
29445     (write-buffered *(ebp+8) ")\n")
29446 $translate-mu-clear-object-stmt:end:
29447     # . restore registers
29448     58/pop-to-eax
29449     # . epilogue
29450     89/<- %esp 5/r32/ebp
29451     5d/pop-to-ebp
29452     c3/return
29453 
29454 translate-mu-allocate-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
29455     # . prologue
29456     55/push-ebp
29457     89/<- %ebp 4/r32/esp
29458     # . save registers
29459     50/push-eax
29460     56/push-esi
29461     57/push-edi
29462     # esi = stmt
29463     8b/-> *(ebp+0xc) 6/r32/esi
29464     # var target/edi: (addr stmt-var) = stmt->inouts[0]
29465     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29466     89/<- %edi 0/r32/eax
29467     #
29468     (emit-indent *(ebp+8) *Curr-block-depth)
29469     (write-buffered *(ebp+8) "(allocate Heap ")
29470     (addr-handle-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
29471     (write-int32-hex-buffered *(ebp+8) %eax)
29472     (emit-subx-call-operand *(ebp+8) %edi)
29473     (write-buffered *(ebp+8) ")\n")
29474 $translate-mu-allocate-stmt:end:
29475     # . restore registers
29476     5f/pop-to-edi
29477     5e/pop-to-esi
29478     58/pop-to-eax
29479     # . epilogue
29480     89/<- %esp 5/r32/ebp
29481     5d/pop-to-ebp
29482     c3/return
29483 
29484 addr-handle-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
29485     # . prologue
29486     55/push-ebp
29487     89/<- %ebp 4/r32/esp
29488     # var t/eax: (addr type-tree) = s->value->type
29489     8b/-> *(ebp+8) 0/r32/eax
29490     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29491     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
29492     # TODO: check eax != 0
29493     # TODO: check !t->is-atom?
29494     # TODO: check t->left == addr
29495     # t = t->right
29496 $addr-handle-payload-size:skip-addr:
29497     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
29498     # TODO: check eax != 0
29499     # TODO: check !t->is-atom?
29500     # TODO: check t->left == handle
29501     # t = t->right
29502 $addr-handle-payload-size:skip-handle:
29503     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
29504     # TODO: check eax != 0
29505     # if !t->is-atom? t = t->left
29506     81 7/subop/compare *eax 0/imm32/false
29507     {
29508       75/jump-if-!= break/disp8
29509       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
29510     }
29511     # TODO: check t->is-atom?
29512     # return size(t->value)
29513     (size-of-type-id *(eax+4))  # Type-tree-value => eax
29514 $addr-handle-payload-size:end:
29515     # . epilogue
29516     89/<- %esp 5/r32/ebp
29517     5d/pop-to-ebp
29518     c3/return
29519 
29520 addr-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
29521     # . prologue
29522     55/push-ebp
29523     89/<- %ebp 4/r32/esp
29524     # var t/eax: (addr type-tree) = s->value->type
29525     8b/-> *(ebp+8) 0/r32/eax
29526     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29527     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
29528     # TODO: check eax != 0
29529     # TODO: check !t->is-atom?
29530     # TODO: check t->left == addr
29531     # t = t->right
29532 $addr-payload-size:skip-addr:
29533     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
29534     # TODO: check eax != 0
29535     # if !t->is-atom? t = t->left
29536     81 7/subop/compare *eax 0/imm32/false
29537     {
29538       75/jump-if-!= break/disp8
29539       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
29540     }
29541     # TODO: check t->is-atom?
29542     # return size(t->value)
29543     (size-of-type-id *(eax+4))  # Type-tree-value => eax
29544 $addr-payload-size:end:
29545     # . epilogue
29546     89/<- %esp 5/r32/ebp
29547     5d/pop-to-ebp
29548     c3/return
29549 
29550 translate-mu-populate-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
29551     # . prologue
29552     55/push-ebp
29553     89/<- %ebp 4/r32/esp
29554     # . save registers
29555     50/push-eax
29556     51/push-ecx
29557     56/push-esi
29558     57/push-edi
29559     # esi = stmt
29560     8b/-> *(ebp+0xc) 6/r32/esi
29561     # var target/edi: (addr stmt-var) = stmt->inouts[0]
29562     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29563     89/<- %edi 0/r32/eax
29564     # var len/ecx: (addr stmt-var) = stmt->inouts[1]
29565     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
29566     89/<- %ecx 0/r32/eax
29567     #
29568     (emit-indent *(ebp+8) *Curr-block-depth)
29569     (write-buffered *(ebp+8) "(allocate-array2 Heap ")
29570     (addr-handle-array-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
29571     (write-int32-hex-buffered *(ebp+8) %eax)
29572     (emit-subx-call-operand *(ebp+8) %ecx)
29573     (emit-subx-call-operand *(ebp+8) %edi)
29574     (write-buffered *(ebp+8) ")\n")
29575 $translate-mu-populate-stmt:end:
29576     # . restore registers
29577     5f/pop-to-edi
29578     5e/pop-to-esi
29579     59/pop-to-ecx
29580     58/pop-to-eax
29581     # . epilogue
29582     89/<- %esp 5/r32/ebp
29583     5d/pop-to-ebp
29584     c3/return
29585 
29586 translate-mu-populate-stream-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
29587     # . prologue
29588     55/push-ebp
29589     89/<- %ebp 4/r32/esp
29590     # . save registers
29591     50/push-eax
29592     51/push-ecx
29593     56/push-esi
29594     57/push-edi
29595     # esi = stmt
29596     8b/-> *(ebp+0xc) 6/r32/esi
29597     # var target/edi: (addr stmt-var) = stmt->inouts[0]
29598     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29599     89/<- %edi 0/r32/eax
29600     # var len/ecx: (addr stmt-var) = stmt->inouts[1]
29601     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
29602     89/<- %ecx 0/r32/eax
29603     #
29604     (emit-indent *(ebp+8) *Curr-block-depth)
29605     (write-buffered *(ebp+8) "(new-stream Heap ")
29606     (addr-handle-stream-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
29607     (write-int32-hex-buffered *(ebp+8) %eax)
29608     (emit-subx-call-operand *(ebp+8) %ecx)
29609     (emit-subx-call-operand *(ebp+8) %edi)
29610     (write-buffered *(ebp+8) ")\n")
29611 $translate-mu-populate-stream-stmt:end:
29612     # . restore registers
29613     5f/pop-to-edi
29614     5e/pop-to-esi
29615     59/pop-to-ecx
29616     58/pop-to-eax
29617     # . epilogue
29618     89/<- %esp 5/r32/ebp
29619     5d/pop-to-ebp
29620     c3/return
29621 
29622 translate-mu-read-from-stream-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
29623     # . prologue
29624     55/push-ebp
29625     89/<- %ebp 4/r32/esp
29626     # . save registers
29627     50/push-eax
29628     51/push-ecx
29629     56/push-esi
29630     57/push-edi
29631     # esi = stmt
29632     8b/-> *(ebp+0xc) 6/r32/esi
29633     # var stream/ecx: (addr stmt-var) = stmt->inouts[0]
29634     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29635     89/<- %ecx 0/r32/eax
29636     # var target/edi: (addr stmt-var) = stmt->inouts[1]
29637     (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
29638     89/<- %edi 0/r32/eax
29639     #
29640     (emit-indent *(ebp+8) *Curr-block-depth)
29641     (write-buffered *(ebp+8) "(read-from-stream")
29642     (emit-subx-call-operand *(ebp+8) %ecx)
29643     (emit-subx-call-operand *(ebp+8) %edi)
29644     (write-buffered *(ebp+8) Space)
29645     (addr-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
29646     (write-int32-hex-buffered *(ebp+8) %eax)
29647     (write-buffered *(ebp+8) ")\n")
29648 $translate-mu-read-from-stream-stmt:end:
29649     # . restore registers
29650     5f/pop-to-edi
29651     5e/pop-to-esi
29652     59/pop-to-ecx
29653     58/pop-to-eax
29654     # . epilogue
29655     89/<- %esp 5/r32/ebp
29656     5d/pop-to-ebp
29657     c3/return
29658 
29659 translate-mu-write-to-stream-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
29660     # . prologue
29661     55/push-ebp
29662     89/<- %ebp 4/r32/esp
29663     # . save registers
29664     50/push-eax
29665     51/push-ecx
29666     56/push-esi
29667     57/push-edi
29668     # esi = stmt
29669     8b/-> *(ebp+0xc) 6/r32/esi
29670     # var stream/ecx: (addr stmt-var) = stmt->inouts[0]
29671     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29672     89/<- %ecx 0/r32/eax
29673     # var target/edi: (addr stmt-var) = stmt->inouts[1]
29674     (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
29675     89/<- %edi 0/r32/eax
29676     #
29677     (emit-indent *(ebp+8) *Curr-block-depth)
29678     (write-buffered *(ebp+8) "(write-to-stream")
29679     (emit-subx-call-operand *(ebp+8) %ecx)
29680     (flush *(ebp+8))
29681     (emit-subx-call-operand *(ebp+8) %edi)
29682     (flush *(ebp+8))
29683     (write-buffered *(ebp+8) Space)
29684     (flush *(ebp+8))
29685     (addr-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
29686     (write-int32-hex-buffered *(ebp+8) %eax)
29687     (write-buffered *(ebp+8) ")\n")
29688 $translate-mu-write-to-stream-stmt:end:
29689     # . restore registers
29690     5f/pop-to-edi
29691     5e/pop-to-esi
29692     59/pop-to-ecx
29693     58/pop-to-eax
29694     # . epilogue
29695     89/<- %esp 5/r32/ebp
29696     5d/pop-to-ebp
29697     c3/return
29698 
29699 addr-handle-array-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
29700     # . prologue
29701     55/push-ebp
29702     89/<- %ebp 4/r32/esp
29703     # var t/eax: (addr type-tree) = s->value->type
29704     8b/-> *(ebp+8) 0/r32/eax
29705     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29706     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
29707     # TODO: check eax != 0
29708     # TODO: check !t->is-atom?
29709     # TODO: check t->left == addr
29710     # t = t->right
29711 $addr-handle-array-payload-size:skip-addr:
29712     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
29713     # TODO: check eax != 0
29714     # TODO: check !t->is-atom?
29715     # TODO: check t->left == handle
29716     # t = t->right
29717 $addr-handle-array-payload-size:skip-handle:
29718     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
29719     # TODO: check eax != 0
29720     # TODO: check !t->is-atom?
29721     # TODO: check t->left == array
29722     # t = t->right
29723 $addr-handle-array-payload-size:skip-array:
29724     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
29725     # TODO: check eax != 0
29726     # if !t->is-atom? t = t->left
29727     81 7/subop/compare *eax 0/imm32/false
29728     {
29729       75/jump-if-!= break/disp8
29730       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
29731     }
29732 $addr-handle-array-payload-size:compute-size:
29733     # TODO: check t->is-atom?
29734     # return size(t->value)
29735     (size-of-type-id-as-array-element *(eax+4))  # Type-tree-value => eax
29736 $addr-handle-array-payload-size:end:
29737     # . epilogue
29738     89/<- %esp 5/r32/ebp
29739     5d/pop-to-ebp
29740     c3/return
29741 
29742 addr-handle-stream-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
29743     # . prologue
29744     55/push-ebp
29745     89/<- %ebp 4/r32/esp
29746     # var t/eax: (addr type-tree) = s->value->type
29747     8b/-> *(ebp+8) 0/r32/eax
29748     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29749     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
29750     # TODO: check eax != 0
29751     # TODO: check !t->is-atom?
29752     # TODO: check t->left == addr
29753     # t = t->right
29754 $addr-handle-stream-payload-size:skip-addr:
29755     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
29756     # TODO: check eax != 0
29757     # TODO: check !t->is-atom?
29758     # TODO: check t->left == handle
29759     # t = t->right
29760 $addr-handle-stream-payload-size:skip-handle:
29761     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
29762     # TODO: check eax != 0
29763     # TODO: check !t->is-atom?
29764     # TODO: check t->left == stream
29765     # t = t->right
29766 $addr-handle-stream-payload-size:skip-stream:
29767     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
29768     # TODO: check eax != 0
29769     # if !t->is-atom? t = t->left
29770     81 7/subop/compare *eax 0/imm32/false
29771     {
29772       75/jump-if-!= break/disp8
29773       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
29774     }
29775 $addr-handle-stream-payload-size:compute-size:
29776     # TODO: check t->is-atom?
29777     # return size(t->value)
29778     (size-of-type-id-as-array-element *(eax+4))  # Type-tree-value => eax
29779 $addr-handle-stream-payload-size:end:
29780     # . epilogue
29781     89/<- %esp 5/r32/ebp
29782     5d/pop-to-ebp
29783     c3/return
29784 
29785 power-of-2?:  # n: int, err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: boolean
29786     # precondition: n is positive
29787     # . prologue
29788     55/push-ebp
29789     89/<- %ebp 4/r32/esp
29790     # eax = n
29791     8b/-> *(ebp+8) 0/r32/eax
29792     # if (n < 0) abort
29793     3d/compare-eax-with 0/imm32
29794     0f 8c/jump-if-< $power-of-2?:abort/disp32
29795     # var tmp/eax: int = n-1
29796     48/decrement-eax
29797     # var tmp2/eax: int = n & tmp
29798     23/and-> *(ebp+8) 0/r32/eax
29799     # return (tmp2 == 0)
29800     3d/compare-eax-and 0/imm32
29801     0f 94/set-byte-if-= %al
29802     81 4/subop/and %eax 0xff/imm32
29803 $power-of-2?:end:
29804     # . epilogue
29805     89/<- %esp 5/r32/ebp
29806     5d/pop-to-ebp
29807     c3/return
29808 
29809 $power-of-2?:abort:
29810     (write-buffered *(ebp+0xc) "power-of-2?: negative number\n")
29811     (flush *(ebp+0xc))
29812     (stop *(ebp+0x10) 1)
29813     # never gets here
29814 
29815 num-shift-rights:  # n: int -> result/eax: int
29816     # precondition: n is a positive power of 2
29817     # . prologue
29818     55/push-ebp
29819     89/<- %ebp 4/r32/esp
29820     # . save registers
29821     51/push-ecx
29822     # var curr/ecx: int = n
29823     8b/-> *(ebp+8) 1/r32/ecx
29824     # result = 0
29825     b8/copy-to-eax 0/imm32
29826     {
29827       # if (curr <= 1) break
29828       81 7/subop/compare %ecx 1/imm32
29829       7e/jump-if-<= break/disp8
29830       40/increment-eax
29831       c1/shift 5/subop/arithmetic-right %ecx 1/imm8
29832       eb/jump loop/disp8
29833     }
29834 $num-shift-rights:end:
29835     # . restore registers
29836     59/pop-to-ecx
29837     # . epilogue
29838     89/<- %esp 5/r32/ebp
29839     5d/pop-to-ebp
29840     c3/return
29841 
29842 mu-get-offset:  # stmt: (addr stmt) -> result/eax: int
29843     # . prologue
29844     55/push-ebp
29845     89/<- %ebp 4/r32/esp
29846     # var second-inout/eax: (addr stmt-var) = stmt->inouts->next
29847     8b/-> *(ebp+8) 0/r32/eax
29848     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29849     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
29850     # var output-var/eax: (addr var) = second-inout->value
29851     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29852 #?     (write-buffered Stderr "mu-get-offset: ")
29853 #?     (write-int32-hex-buffered Stderr %eax)
29854 #?     (write-buffered Stderr " name: ")
29855 #?     50/push-eax
29856 #?     (lookup *eax *(eax+4))  # Var-name
29857 #?     (write-buffered Stderr %eax)
29858 #?     58/pop-to-eax
29859 #?     (write-buffered Stderr Newline)
29860 #?     (flush Stderr)
29861     # return output-var->stack-offset
29862     8b/-> *(eax+0x14) 0/r32/eax  # Var-offset
29863 #?     (write-buffered Stderr "=> ")
29864 #?     (write-int32-hex-buffered Stderr %eax)
29865 #?     (write-buffered Stderr Newline)
29866 #?     (flush Stderr)
29867 $emit-get-offset:end:
29868     # . epilogue
29869     89/<- %esp 5/r32/ebp
29870     5d/pop-to-ebp
29871     c3/return
29872 
29873 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)
29874     # . prologue
29875     55/push-ebp
29876     89/<- %ebp 4/r32/esp
29877     # . save registers
29878     50/push-eax
29879     51/push-ecx
29880     56/push-esi
29881     # esi = block
29882     8b/-> *(ebp+0xc) 6/r32/esi
29883     # block->var->block-depth = *Curr-block-depth
29884     (lookup *(esi+0xc) *(esi+0x10))  # Block-var Block-var => eax
29885     8b/-> *Curr-block-depth 1/r32/ecx
29886     89/<- *(eax+0x10) 1/r32/ecx  # Var-block-depth
29887     # var stmts/eax: (addr list stmt) = lookup(block->statements)
29888     (lookup *(esi+4) *(esi+8))  # Block-stmts Block-stmts => eax
29889     #
29890     {
29891 $emit-subx-block:check-empty:
29892       3d/compare-eax-and 0/imm32
29893       0f 84/jump-if-= break/disp32
29894       (emit-indent *(ebp+8) *Curr-block-depth)
29895       (write-buffered *(ebp+8) "{\n")
29896       # var v/ecx: (addr var) = lookup(block->var)
29897       (lookup *(esi+0xc) *(esi+0x10))  # Block-var Block-var => eax
29898       89/<- %ecx 0/r32/eax
29899       #
29900       (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
29901       (write-buffered *(ebp+8) %eax)
29902       (write-buffered *(ebp+8) ":loop:\n")
29903       ff 0/subop/increment *Curr-block-depth
29904       (push *(ebp+0x10) *(esi+0xc))  # Block-var
29905       (push *(ebp+0x10) *(esi+0x10))  # Block-var
29906       (push *(ebp+0x10) 0)  # false
29907       # emit block->statements
29908       (lookup *(esi+4) *(esi+8))  # Block-stmts Block-stmts => eax
29909       (emit-subx-stmt-list *(ebp+8) %eax *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
29910       (pop *(ebp+0x10))  # => eax
29911       (pop *(ebp+0x10))  # => eax
29912       (pop *(ebp+0x10))  # => eax
29913       ff 1/subop/decrement *Curr-block-depth
29914       (emit-indent *(ebp+8) *Curr-block-depth)
29915       (write-buffered *(ebp+8) "}\n")
29916       (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
29917       (write-buffered *(ebp+8) %eax)
29918       (write-buffered *(ebp+8) ":break:\n")
29919     }
29920 $emit-subx-block:end:
29921     # . restore registers
29922     5e/pop-to-esi
29923     59/pop-to-ecx
29924     58/pop-to-eax
29925     # . epilogue
29926     89/<- %esp 5/r32/ebp
29927     5d/pop-to-ebp
29928     c3/return
29929 
29930 # Primitives supported
29931 # See mu_instructions for a summary of this linked-list data structure.
29932 #
29933 # For each operation, put variants with hard-coded registers before flexible ones.
29934 #
29935 # Unfortunately, our restrictions on addresses require that various fields in
29936 # primitives be handles, which complicates these definitions.
29937 #   - we need to insert dummy fields all over the place for fake alloc-ids
29938 #   - we can't use our syntax sugar of quoted literals for string fields
29939 #
29940 # Fake alloc-ids are needed because our type definitions up top require
29941 # handles but it's clearer to statically allocate these long-lived objects.
29942 # Fake alloc-ids are perfectly safe, but they can't be reclaimed.
29943 #
29944 # Every 'object' below starts with a fake alloc-id. It may also contain other
29945 # fake alloc-ids for various handle fields.
29946 #
29947 # I think of objects starting with a fake alloc-id as having type 'payload'.
29948 # It's not really intended to be created dynamically; for that use `allocate`
29949 # as usual.
29950 #
29951 # Idea for a notation to simplify such definitions:
29952 #   _Primitive-increment-eax:  # (payload primitive)
29953 #     0x11/alloc-id:fake:payload
29954 #     0x11 @(0x11 "increment")  # name
29955 #     0 0                       # inouts
29956 #     0x11 @(0x11/payload
29957 #            0x11 @(0x11/payload  # List-value
29958 #                   0 0             # Var-name
29959 #                   0x11 @(0x11     # Var-type
29960 #                          1/is-atom
29961 #                          1/value 0/unused   # Type-tree-left
29962 #                          0 0                # Type-tree-right
29963 #                         )
29964 #                   1               # block-depth
29965 #                   0               # stack-offset
29966 #                   0x11 @(0x11 "eax")  # Var-register
29967 #                  )
29968 #            0 0)                 # List-next
29969 #     ...
29970 #     _Primitive-increment-ecx/imm32/next
29971 #   ...
29972 # Awfully complex and non-obvious. But also clearly signals there's something
29973 # to learn here, so may be worth trying.
29974 #
29975 # '@' is just an initial thought. Punctuation used so far in Mu: () * % # / "
29976 #
29977 # For now we'll continue to just use comments and manually ensure they stay up
29978 # to date.
29979 == data
29980 Primitives:  # (addr primitive)
29981 # - increment/decrement
29982 _Primitive-increment-eax:  # (addr primitive)
29983     # var/eax <- increment => 40/increment-eax
29984     0x11/imm32/alloc-id:fake
29985     _string-increment/imm32/name
29986     0/imm32/no-inouts
29987     0/imm32/no-inouts
29988     0x11/imm32/alloc-id:fake
29989     Single-int-var-in-eax/imm32/outputs
29990     0x11/imm32/alloc-id:fake
29991     _string_40_increment_eax/imm32/subx-name
29992     0/imm32/no-rm32
29993     0/imm32/no-r32
29994     0/imm32/no-imm32
29995     0/imm32/no-imm8
29996     0/imm32/no-disp32
29997     0/imm32/no-xm32
29998     0/imm32/no-x32
29999     0x11/imm32/alloc-id:fake
30000     _Primitive-increment-ecx/imm32/next
30001 _Primitive-increment-ecx:  # (payload primitive)
30002     0x11/imm32/alloc-id:fake:payload
30003     # var/ecx <- increment => 41/increment-ecx
30004     0x11/imm32/alloc-id:fake
30005     _string-increment/imm32/name
30006     0/imm32/no-inouts
30007     0/imm32/no-inouts
30008     0x11/imm32/alloc-id:fake
30009     Single-int-var-in-ecx/imm32/outputs
30010     0x11/imm32/alloc-id:fake
30011     _string_41_increment_ecx/imm32/subx-name
30012     0/imm32/no-rm32
30013     0/imm32/no-r32
30014     0/imm32/no-imm32
30015     0/imm32/no-imm8
30016     0/imm32/no-disp32
30017     0/imm32/no-xm32
30018     0/imm32/no-x32
30019     0x11/imm32/alloc-id:fake
30020     _Primitive-increment-edx/imm32/next
30021 _Primitive-increment-edx:  # (payload primitive)
30022     0x11/imm32/alloc-id:fake:payload
30023     # var/edx <- increment => 42/increment-edx
30024     0x11/imm32/alloc-id:fake
30025     _string-increment/imm32/name
30026     0/imm32/no-inouts
30027     0/imm32/no-inouts
30028     0x11/imm32/alloc-id:fake
30029     Single-int-var-in-edx/imm32/outputs
30030     0x11/imm32/alloc-id:fake
30031     _string_42_increment_edx/imm32/subx-name
30032     0/imm32/no-rm32
30033     0/imm32/no-r32
30034     0/imm32/no-imm32
30035     0/imm32/no-imm8
30036     0/imm32/no-disp32
30037     0/imm32/no-xm32
30038     0/imm32/no-x32
30039     0x11/imm32/alloc-id:fake
30040     _Primitive-increment-ebx/imm32/next
30041 _Primitive-increment-ebx:  # (payload primitive)
30042     0x11/imm32/alloc-id:fake:payload
30043     # var/ebx <- increment => 43/increment-ebx
30044     0x11/imm32/alloc-id:fake
30045     _string-increment/imm32/name
30046     0/imm32/no-inouts
30047     0/imm32/no-inouts
30048     0x11/imm32/alloc-id:fake
30049     Single-int-var-in-ebx/imm32/outputs
30050     0x11/imm32/alloc-id:fake
30051     _string_43_increment_ebx/imm32/subx-name
30052     0/imm32/no-rm32
30053     0/imm32/no-r32
30054     0/imm32/no-imm32
30055     0/imm32/no-imm8
30056     0/imm32/no-disp32
30057     0/imm32/no-xm32
30058     0/imm32/no-x32
30059     0x11/imm32/alloc-id:fake
30060     _Primitive-increment-esi/imm32/next
30061 _Primitive-increment-esi:  # (payload primitive)
30062     0x11/imm32/alloc-id:fake:payload
30063     # var/esi <- increment => 46/increment-esi
30064     0x11/imm32/alloc-id:fake
30065     _string-increment/imm32/name
30066     0/imm32/no-inouts
30067     0/imm32/no-inouts
30068     0x11/imm32/alloc-id:fake
30069     Single-int-var-in-esi/imm32/outputs
30070     0x11/imm32/alloc-id:fake
30071     _string_46_increment_esi/imm32/subx-name
30072     0/imm32/no-rm32
30073     0/imm32/no-r32
30074     0/imm32/no-imm32
30075     0/imm32/no-imm8
30076     0/imm32/no-disp32
30077     0/imm32/no-xm32
30078     0/imm32/no-x32
30079     0x11/imm32/alloc-id:fake
30080     _Primitive-increment-edi/imm32/next
30081 _Primitive-increment-edi:  # (payload primitive)
30082     0x11/imm32/alloc-id:fake:payload
30083     # var/edi <- increment => 47/increment-edi
30084     0x11/imm32/alloc-id:fake
30085     _string-increment/imm32/name
30086     0/imm32/no-inouts
30087     0/imm32/no-inouts
30088     0x11/imm32/alloc-id:fake
30089     Single-int-var-in-edi/imm32/outputs
30090     0x11/imm32/alloc-id:fake
30091     _string_47_increment_edi/imm32/subx-name
30092     0/imm32/no-rm32
30093     0/imm32/no-r32
30094     0/imm32/no-imm32
30095     0/imm32/no-imm8
30096     0/imm32/no-disp32
30097     0/imm32/no-xm32
30098     0/imm32/no-x32
30099     0x11/imm32/alloc-id:fake
30100     _Primitive-decrement-eax/imm32/next
30101 _Primitive-decrement-eax:  # (payload primitive)
30102     0x11/imm32/alloc-id:fake:payload
30103     # var/eax <- decrement => 48/decrement-eax
30104     0x11/imm32/alloc-id:fake
30105     _string-decrement/imm32/name
30106     0/imm32/no-inouts
30107     0/imm32/no-inouts
30108     0x11/imm32/alloc-id:fake
30109     Single-int-var-in-eax/imm32/outputs
30110     0x11/imm32/alloc-id:fake
30111     _string_48_decrement_eax/imm32/subx-name
30112     0/imm32/no-rm32
30113     0/imm32/no-r32
30114     0/imm32/no-imm32
30115     0/imm32/no-imm8
30116     0/imm32/no-disp32
30117     0/imm32/no-xm32
30118     0/imm32/no-x32
30119     0x11/imm32/alloc-id:fake
30120     _Primitive-decrement-ecx/imm32/next
30121 _Primitive-decrement-ecx:  # (payload primitive)
30122     0x11/imm32/alloc-id:fake:payload
30123     # var/ecx <- decrement => 49/decrement-ecx
30124     0x11/imm32/alloc-id:fake
30125     _string-decrement/imm32/name
30126     0/imm32/no-inouts
30127     0/imm32/no-inouts
30128     0x11/imm32/alloc-id:fake
30129     Single-int-var-in-ecx/imm32/outputs
30130     0x11/imm32/alloc-id:fake
30131     _string_49_decrement_ecx/imm32/subx-name
30132     0/imm32/no-rm32
30133     0/imm32/no-r32
30134     0/imm32/no-imm32
30135     0/imm32/no-imm8
30136     0/imm32/no-disp32
30137     0/imm32/no-xm32
30138     0/imm32/no-x32
30139     0x11/imm32/alloc-id:fake
30140     _Primitive-decrement-edx/imm32/next
30141 _Primitive-decrement-edx:  # (payload primitive)
30142     0x11/imm32/alloc-id:fake:payload
30143     # var/edx <- decrement => 4a/decrement-edx
30144     0x11/imm32/alloc-id:fake
30145     _string-decrement/imm32/name
30146     0/imm32/no-inouts
30147     0/imm32/no-inouts
30148     0x11/imm32/alloc-id:fake
30149     Single-int-var-in-edx/imm32/outputs
30150     0x11/imm32/alloc-id:fake
30151     _string_4a_decrement_edx/imm32/subx-name
30152     0/imm32/no-rm32
30153     0/imm32/no-r32
30154     0/imm32/no-imm32
30155     0/imm32/no-imm8
30156     0/imm32/no-disp32
30157     0/imm32/no-xm32
30158     0/imm32/no-x32
30159     0x11/imm32/alloc-id:fake
30160     _Primitive-decrement-ebx/imm32/next
30161 _Primitive-decrement-ebx:  # (payload primitive)
30162     0x11/imm32/alloc-id:fake:payload
30163     # var/ebx <- decrement => 4b/decrement-ebx
30164     0x11/imm32/alloc-id:fake
30165     _string-decrement/imm32/name
30166     0/imm32/no-inouts
30167     0/imm32/no-inouts
30168     0x11/imm32/alloc-id:fake
30169     Single-int-var-in-ebx/imm32/outputs
30170     0x11/imm32/alloc-id:fake
30171     _string_4b_decrement_ebx/imm32/subx-name
30172     0/imm32/no-rm32
30173     0/imm32/no-r32
30174     0/imm32/no-imm32
30175     0/imm32/no-imm8
30176     0/imm32/no-disp32
30177     0/imm32/no-xm32
30178     0/imm32/no-x32
30179     0x11/imm32/alloc-id:fake
30180     _Primitive-decrement-esi/imm32/next
30181 _Primitive-decrement-esi:  # (payload primitive)
30182     0x11/imm32/alloc-id:fake:payload
30183     # var/esi <- decrement => 4e/decrement-esi
30184     0x11/imm32/alloc-id:fake
30185     _string-decrement/imm32/name
30186     0/imm32/no-inouts
30187     0/imm32/no-inouts
30188     0x11/imm32/alloc-id:fake
30189     Single-int-var-in-esi/imm32/outputs
30190     0x11/imm32/alloc-id:fake
30191     _string_4e_decrement_esi/imm32/subx-name
30192     0/imm32/no-rm32
30193     0/imm32/no-r32
30194     0/imm32/no-imm32
30195     0/imm32/no-imm8
30196     0/imm32/no-disp32
30197     0/imm32/no-xm32
30198     0/imm32/no-x32
30199     0x11/imm32/alloc-id:fake
30200     _Primitive-decrement-edi/imm32/next
30201 _Primitive-decrement-edi:  # (payload primitive)
30202     0x11/imm32/alloc-id:fake:payload
30203     # var/edi <- decrement => 4f/decrement-edi
30204     0x11/imm32/alloc-id:fake
30205     _string-decrement/imm32/name
30206     0/imm32/no-inouts
30207     0/imm32/no-inouts
30208     0x11/imm32/alloc-id:fake
30209     Single-int-var-in-edi/imm32/outputs
30210     0x11/imm32/alloc-id:fake
30211     _string_4f_decrement_edi/imm32/subx-name
30212     0/imm32/no-rm32
30213     0/imm32/no-r32
30214     0/imm32/no-imm32
30215     0/imm32/no-imm8
30216     0/imm32/no-disp32
30217     0/imm32/no-xm32
30218     0/imm32/no-x32
30219     0x11/imm32/alloc-id:fake
30220     _Primitive-increment-mem/imm32/next
30221 _Primitive-increment-mem:  # (payload primitive)
30222     0x11/imm32/alloc-id:fake:payload
30223     # increment var => ff 0/subop/increment *(ebp+__)
30224     0x11/imm32/alloc-id:fake
30225     _string-increment/imm32/name
30226     0x11/imm32/alloc-id:fake
30227     Single-int-var-in-mem/imm32/inouts
30228     0/imm32/no-outputs
30229     0/imm32/no-outputs
30230     0x11/imm32/alloc-id:fake
30231     _string_ff_subop_increment/imm32/subx-name
30232     1/imm32/rm32-is-first-inout
30233     0/imm32/no-r32
30234     0/imm32/no-imm32
30235     0/imm32/no-imm8
30236     0/imm32/no-disp32
30237     0/imm32/no-xm32
30238     0/imm32/no-x32
30239     0x11/imm32/alloc-id:fake
30240     _Primitive-increment-reg/imm32/next
30241 _Primitive-increment-reg:  # (payload primitive)
30242     0x11/imm32/alloc-id:fake:payload
30243     # var/reg <- increment => ff 0/subop/increment %__
30244     0x11/imm32/alloc-id:fake
30245     _string-increment/imm32/name
30246     0/imm32/no-inouts
30247     0/imm32/no-inouts
30248     0x11/imm32/alloc-id:fake
30249     Single-int-var-in-some-register/imm32/outputs
30250     0x11/imm32/alloc-id:fake
30251     _string_ff_subop_increment/imm32/subx-name
30252     3/imm32/rm32-is-first-output
30253     0/imm32/no-r32
30254     0/imm32/no-imm32
30255     0/imm32/no-imm8
30256     0/imm32/no-disp32
30257     0/imm32/no-xm32
30258     0/imm32/no-x32
30259     0x11/imm32/alloc-id:fake
30260     _Primitive-decrement-mem/imm32/next
30261 _Primitive-decrement-mem:  # (payload primitive)
30262     0x11/imm32/alloc-id:fake:payload
30263     # decrement var => ff 1/subop/decrement *(ebp+__)
30264     0x11/imm32/alloc-id:fake
30265     _string-decrement/imm32/name
30266     0x11/imm32/alloc-id:fake
30267     Single-int-var-in-mem/imm32/inouts
30268     0/imm32/no-outputs
30269     0/imm32/no-outputs
30270     0x11/imm32/alloc-id:fake
30271     _string_ff_subop_decrement/imm32/subx-name
30272     1/imm32/rm32-is-first-inout
30273     0/imm32/no-r32
30274     0/imm32/no-imm32
30275     0/imm32/no-imm8
30276     0/imm32/no-disp32
30277     0/imm32/no-xm32
30278     0/imm32/no-x32
30279     0x11/imm32/alloc-id:fake
30280     _Primitive-decrement-reg/imm32/next
30281 _Primitive-decrement-reg:  # (payload primitive)
30282     0x11/imm32/alloc-id:fake:payload
30283     # var/reg <- decrement => ff 1/subop/decrement %__
30284     0x11/imm32/alloc-id:fake
30285     _string-decrement/imm32/name
30286     0/imm32/no-inouts
30287     0/imm32/no-inouts
30288     0x11/imm32/alloc-id:fake
30289     Single-int-var-in-some-register/imm32/outputs
30290     0x11/imm32/alloc-id:fake
30291     _string_ff_subop_decrement/imm32/subx-name
30292     3/imm32/rm32-is-first-output
30293     0/imm32/no-r32
30294     0/imm32/no-imm32
30295     0/imm32/no-imm8
30296     0/imm32/no-disp32
30297     0/imm32/no-xm32
30298     0/imm32/no-x32
30299     0x11/imm32/alloc-id:fake
30300     _Primitive-add-to-eax/imm32/next
30301 # - add
30302 _Primitive-add-to-eax:  # (payload primitive)
30303     0x11/imm32/alloc-id:fake:payload
30304     # var/eax <- add lit => 05/add-to-eax lit/imm32
30305     0x11/imm32/alloc-id:fake
30306     _string-add/imm32/name
30307     0x11/imm32/alloc-id:fake
30308     Single-lit-var/imm32/inouts
30309     0x11/imm32/alloc-id:fake
30310     Single-int-var-in-eax/imm32/outputs
30311     0x11/imm32/alloc-id:fake
30312     _string_05_add_to_eax/imm32/subx-name
30313     0/imm32/no-rm32
30314     0/imm32/no-r32
30315     1/imm32/imm32-is-first-inout
30316     0/imm32/no-imm8
30317     0/imm32/no-disp32
30318     0/imm32/no-xm32
30319     0/imm32/no-x32
30320     0x11/imm32/alloc-id:fake
30321     _Primitive-add-reg-to-reg/imm32/next
30322 _Primitive-add-reg-to-reg:  # (payload primitive)
30323     0x11/imm32/alloc-id:fake:payload
30324     # var1/reg <- add var2/reg => 01/add-to var1/rm32 var2/r32
30325     0x11/imm32/alloc-id:fake
30326     _string-add/imm32/name
30327     0x11/imm32/alloc-id:fake
30328     Single-int-var-in-some-register/imm32/inouts
30329     0x11/imm32/alloc-id:fake
30330     Single-int-var-in-some-register/imm32/outputs
30331     0x11/imm32/alloc-id:fake
30332     _string_01_add_to/imm32/subx-name
30333     3/imm32/rm32-is-first-output
30334     1/imm32/r32-is-first-inout
30335     0/imm32/no-imm32
30336     0/imm32/no-imm8
30337     0/imm32/no-disp32
30338     0/imm32/no-xm32
30339     0/imm32/no-x32
30340     0x11/imm32/alloc-id:fake
30341     _Primitive-add-reg-to-mem/imm32/next
30342 _Primitive-add-reg-to-mem:  # (payload primitive)
30343     0x11/imm32/alloc-id:fake:payload
30344     # add-to var1 var2/reg => 01/add-to var1 var2/r32
30345     0x11/imm32/alloc-id:fake
30346     _string-add-to/imm32/name
30347     0x11/imm32/alloc-id:fake
30348     Two-args-int-stack-int-reg/imm32/inouts
30349     0/imm32/no-outputs
30350     0/imm32/no-outputs
30351     0x11/imm32/alloc-id:fake
30352     _string_01_add_to/imm32/subx-name
30353     1/imm32/rm32-is-first-inout
30354     2/imm32/r32-is-second-inout
30355     0/imm32/no-imm32
30356     0/imm32/no-imm8
30357     0/imm32/no-disp32
30358     0/imm32/no-xm32
30359     0/imm32/no-x32
30360     0x11/imm32/alloc-id:fake
30361     _Primitive-add-mem-to-reg/imm32/next
30362 _Primitive-add-mem-to-reg:  # (payload primitive)
30363     0x11/imm32/alloc-id:fake:payload
30364     # var1/reg <- add var2 => 03/add var2/rm32 var1/r32
30365     0x11/imm32/alloc-id:fake
30366     _string-add/imm32/name
30367     0x11/imm32/alloc-id:fake
30368     Single-int-var-in-mem/imm32/inouts
30369     0x11/imm32/alloc-id:fake
30370     Single-int-var-in-some-register/imm32/outputs
30371     0x11/imm32/alloc-id:fake
30372     _string_03_add/imm32/subx-name
30373     1/imm32/rm32-is-first-inout
30374     3/imm32/r32-is-first-output
30375     0/imm32/no-imm32
30376     0/imm32/no-imm8
30377     0/imm32/no-disp32
30378     0/imm32/no-xm32
30379     0/imm32/no-x32
30380     0x11/imm32/alloc-id:fake
30381     _Primitive-add-lit-to-reg/imm32/next
30382 _Primitive-add-lit-to-reg:  # (payload primitive)
30383     0x11/imm32/alloc-id:fake:payload
30384     # var1/reg <- add lit => 81 0/subop/add var1/rm32 lit/imm32
30385     0x11/imm32/alloc-id:fake
30386     _string-add/imm32/name
30387     0x11/imm32/alloc-id:fake
30388     Single-lit-var/imm32/inouts
30389     0x11/imm32/alloc-id:fake
30390     Single-int-var-in-some-register/imm32/outputs
30391     0x11/imm32/alloc-id:fake
30392     _string_81_subop_add/imm32/subx-name
30393     3/imm32/rm32-is-first-output
30394     0/imm32/no-r32
30395     1/imm32/imm32-is-first-inout
30396     0/imm32/no-imm8
30397     0/imm32/no-disp32
30398     0/imm32/no-xm32
30399     0/imm32/no-x32
30400     0x11/imm32/alloc-id:fake
30401     _Primitive-add-lit-to-mem/imm32/next
30402 _Primitive-add-lit-to-mem:  # (payload primitive)
30403     0x11/imm32/alloc-id:fake:payload
30404     # add-to var1, lit => 81 0/subop/add var1/rm32 lit/imm32
30405     0x11/imm32/alloc-id:fake
30406     _string-add-to/imm32/name
30407     0x11/imm32/alloc-id:fake
30408     Int-var-and-literal/imm32/inouts
30409     0/imm32/no-outputs
30410     0/imm32/no-outputs
30411     0x11/imm32/alloc-id:fake
30412     _string_81_subop_add/imm32/subx-name
30413     1/imm32/rm32-is-first-inout
30414     0/imm32/no-r32
30415     2/imm32/imm32-is-second-inout
30416     0/imm32/no-imm8
30417     0/imm32/no-disp32
30418     0/imm32/no-xm32
30419     0/imm32/no-x32
30420     0x11/imm32/alloc-id:fake
30421     _Primitive-subtract-from-eax/imm32/next
30422 # - subtract
30423 _Primitive-subtract-from-eax:  # (payload primitive)
30424     0x11/imm32/alloc-id:fake:payload
30425     # var/eax <- subtract lit => 2d/subtract-from-eax lit/imm32
30426     0x11/imm32/alloc-id:fake
30427     _string-subtract/imm32/name
30428     0x11/imm32/alloc-id:fake
30429     Single-lit-var/imm32/inouts
30430     0x11/imm32/alloc-id:fake
30431     Single-int-var-in-eax/imm32/outputs
30432     0x11/imm32/alloc-id:fake
30433     _string_2d_subtract_from_eax/imm32/subx-name
30434     0/imm32/no-rm32
30435     0/imm32/no-r32
30436     1/imm32/imm32-is-first-inout
30437     0/imm32/no-imm8
30438     0/imm32/no-disp32
30439     0/imm32/no-xm32
30440     0/imm32/no-x32
30441     0x11/imm32/alloc-id:fake
30442     _Primitive-subtract-reg-from-reg/imm32/next
30443 _Primitive-subtract-reg-from-reg:  # (payload primitive)
30444     0x11/imm32/alloc-id:fake:payload
30445     # var1/reg <- subtract var2/reg => 29/subtract-from var1/rm32 var2/r32
30446     0x11/imm32/alloc-id:fake
30447     _string-subtract/imm32/name
30448     0x11/imm32/alloc-id:fake
30449     Single-int-var-in-some-register/imm32/inouts
30450     0x11/imm32/alloc-id:fake
30451     Single-int-var-in-some-register/imm32/outputs
30452     0x11/imm32/alloc-id:fake
30453     _string_29_subtract_from/imm32/subx-name
30454     3/imm32/rm32-is-first-output
30455     1/imm32/r32-is-first-inout
30456     0/imm32/no-imm32
30457     0/imm32/no-imm8
30458     0/imm32/no-disp32
30459     0/imm32/no-xm32
30460     0/imm32/no-x32
30461     0x11/imm32/alloc-id:fake
30462     _Primitive-subtract-reg-from-mem/imm32/next
30463 _Primitive-subtract-reg-from-mem:  # (payload primitive)
30464     0x11/imm32/alloc-id:fake:payload
30465     # subtract-from var1 var2/reg => 29/subtract-from var1 var2/r32
30466     0x11/imm32/alloc-id:fake
30467     _string-subtract-from/imm32/name
30468     0x11/imm32/alloc-id:fake
30469     Two-args-int-stack-int-reg/imm32/inouts
30470     0/imm32/no-outputs
30471     0/imm32/no-outputs
30472     0x11/imm32/alloc-id:fake
30473     _string_29_subtract_from/imm32/subx-name
30474     1/imm32/rm32-is-first-inout
30475     2/imm32/r32-is-second-inout
30476     0/imm32/no-imm32
30477     0/imm32/no-imm8
30478     0/imm32/no-disp32
30479     0/imm32/no-xm32
30480     0/imm32/no-x32
30481     0x11/imm32/alloc-id:fake
30482     _Primitive-subtract-mem-from-reg/imm32/next
30483 _Primitive-subtract-mem-from-reg:  # (payload primitive)
30484     0x11/imm32/alloc-id:fake:payload
30485     # var1/reg <- subtract var2 => 2b/subtract var2/rm32 var1/r32
30486     0x11/imm32/alloc-id:fake
30487     _string-subtract/imm32/name
30488     0x11/imm32/alloc-id:fake
30489     Single-int-var-in-mem/imm32/inouts
30490     0x11/imm32/alloc-id:fake
30491     Single-int-var-in-some-register/imm32/outputs
30492     0x11/imm32/alloc-id:fake
30493     _string_2b_subtract/imm32/subx-name
30494     1/imm32/rm32-is-first-inout
30495     3/imm32/r32-is-first-output
30496     0/imm32/no-imm32
30497     0/imm32/no-imm8
30498     0/imm32/no-disp32
30499     0/imm32/no-xm32
30500     0/imm32/no-x32
30501     0x11/imm32/alloc-id:fake
30502     _Primitive-subtract-lit-from-reg/imm32/next
30503 _Primitive-subtract-lit-from-reg:  # (payload primitive)
30504     0x11/imm32/alloc-id:fake:payload
30505     # var1/reg <- subtract lit => 81 5/subop/subtract var1/rm32 lit/imm32
30506     0x11/imm32/alloc-id:fake
30507     _string-subtract/imm32/name
30508     0x11/imm32/alloc-id:fake
30509     Single-lit-var/imm32/inouts
30510     0x11/imm32/alloc-id:fake
30511     Single-int-var-in-some-register/imm32/outputs
30512     0x11/imm32/alloc-id:fake
30513     _string_81_subop_subtract/imm32/subx-name
30514     3/imm32/rm32-is-first-output
30515     0/imm32/no-r32
30516     1/imm32/imm32-is-first-inout
30517     0/imm32/no-imm8
30518     0/imm32/no-disp32
30519     0/imm32/no-xm32
30520     0/imm32/no-x32
30521     0x11/imm32/alloc-id:fake
30522     _Primitive-subtract-lit-from-mem/imm32/next
30523 _Primitive-subtract-lit-from-mem:  # (payload primitive)
30524     0x11/imm32/alloc-id:fake:payload
30525     # subtract-from var1, lit => 81 5/subop/subtract var1/rm32 lit/imm32
30526     0x11/imm32/alloc-id:fake
30527     _string-subtract-from/imm32/name
30528     0x11/imm32/alloc-id:fake
30529     Int-var-and-literal/imm32/inouts
30530     0/imm32/no-outputs
30531     0/imm32/no-outputs
30532     0x11/imm32/alloc-id:fake
30533     _string_81_subop_subtract/imm32/subx-name
30534     1/imm32/rm32-is-first-inout
30535     0/imm32/no-r32
30536     2/imm32/imm32-is-second-inout
30537     0/imm32/no-imm8
30538     0/imm32/no-disp32
30539     0/imm32/no-xm32
30540     0/imm32/no-x32
30541     0x11/imm32/alloc-id:fake
30542     _Primitive-and-with-eax/imm32/next
30543 # - and
30544 _Primitive-and-with-eax:  # (payload primitive)
30545     0x11/imm32/alloc-id:fake:payload
30546     # var/eax <- and lit => 25/and-with-eax lit/imm32
30547     0x11/imm32/alloc-id:fake
30548     _string-and/imm32/name
30549     0x11/imm32/alloc-id:fake
30550     Single-lit-var/imm32/inouts
30551     0x11/imm32/alloc-id:fake
30552     Single-int-var-in-eax/imm32/outputs
30553     0x11/imm32/alloc-id:fake
30554     _string_25_and_with_eax/imm32/subx-name
30555     0/imm32/no-rm32
30556     0/imm32/no-r32
30557     1/imm32/imm32-is-first-inout
30558     0/imm32/no-imm8
30559     0/imm32/no-disp32
30560     0/imm32/no-xm32
30561     0/imm32/no-x32
30562     0x11/imm32/alloc-id:fake
30563     _Primitive-and-reg-with-reg/imm32/next
30564 _Primitive-and-reg-with-reg:  # (payload primitive)
30565     0x11/imm32/alloc-id:fake:payload
30566     # var1/reg <- and var2/reg => 21/and-with var1/rm32 var2/r32
30567     0x11/imm32/alloc-id:fake
30568     _string-and/imm32/name
30569     0x11/imm32/alloc-id:fake
30570     Single-int-var-in-some-register/imm32/inouts
30571     0x11/imm32/alloc-id:fake
30572     Single-int-var-in-some-register/imm32/outputs
30573     0x11/imm32/alloc-id:fake
30574     _string_21_and_with/imm32/subx-name
30575     3/imm32/rm32-is-first-output
30576     1/imm32/r32-is-first-inout
30577     0/imm32/no-imm32
30578     0/imm32/no-imm8
30579     0/imm32/no-disp32
30580     0/imm32/no-xm32
30581     0/imm32/no-x32
30582     0x11/imm32/alloc-id:fake
30583     _Primitive-and-reg-with-mem/imm32/next
30584 _Primitive-and-reg-with-mem:  # (payload primitive)
30585     0x11/imm32/alloc-id:fake:payload
30586     # and-with var1 var2/reg => 21/and-with var1 var2/r32
30587     0x11/imm32/alloc-id:fake
30588     _string-and-with/imm32/name
30589     0x11/imm32/alloc-id:fake
30590     Two-args-int-stack-int-reg/imm32/inouts
30591     0/imm32/no-outputs
30592     0/imm32/no-outputs
30593     0x11/imm32/alloc-id:fake
30594     _string_21_and_with/imm32/subx-name
30595     1/imm32/rm32-is-first-inout
30596     2/imm32/r32-is-second-inout
30597     0/imm32/no-imm32
30598     0/imm32/no-imm8
30599     0/imm32/no-disp32
30600     0/imm32/no-xm32
30601     0/imm32/no-x32
30602     0x11/imm32/alloc-id:fake
30603     _Primitive-and-mem-with-reg/imm32/next
30604 _Primitive-and-mem-with-reg:  # (payload primitive)
30605     0x11/imm32/alloc-id:fake:payload
30606     # var1/reg <- and var2 => 23/and var2/rm32 var1/r32
30607     0x11/imm32/alloc-id:fake
30608     _string-and/imm32/name
30609     0x11/imm32/alloc-id:fake
30610     Single-int-var-in-mem/imm32/inouts
30611     0x11/imm32/alloc-id:fake
30612     Single-int-var-in-some-register/imm32/outputs
30613     0x11/imm32/alloc-id:fake
30614     _string_23_and/imm32/subx-name
30615     1/imm32/rm32-is-first-inout
30616     3/imm32/r32-is-first-output
30617     0/imm32/no-imm32
30618     0/imm32/no-imm8
30619     0/imm32/no-disp32
30620     0/imm32/no-xm32
30621     0/imm32/no-x32
30622     0x11/imm32/alloc-id:fake
30623     _Primitive-and-lit-with-reg/imm32/next
30624 _Primitive-and-lit-with-reg:  # (payload primitive)
30625     0x11/imm32/alloc-id:fake:payload
30626     # var1/reg <- and lit => 81 4/subop/and var1/rm32 lit/imm32
30627     0x11/imm32/alloc-id:fake
30628     _string-and/imm32/name
30629     0x11/imm32/alloc-id:fake
30630     Single-lit-var/imm32/inouts
30631     0x11/imm32/alloc-id:fake
30632     Single-int-var-in-some-register/imm32/outputs
30633     0x11/imm32/alloc-id:fake
30634     _string_81_subop_and/imm32/subx-name
30635     3/imm32/rm32-is-first-output
30636     0/imm32/no-r32
30637     1/imm32/imm32-is-first-inout
30638     0/imm32/no-imm8
30639     0/imm32/no-disp32
30640     0/imm32/no-xm32
30641     0/imm32/no-x32
30642     0x11/imm32/alloc-id:fake
30643     _Primitive-and-lit-with-mem/imm32/next
30644 _Primitive-and-lit-with-mem:  # (payload primitive)
30645     0x11/imm32/alloc-id:fake:payload
30646     # and-with var1, lit => 81 4/subop/and var1/rm32 lit/imm32
30647     0x11/imm32/alloc-id:fake
30648     _string-and-with/imm32/name
30649     0x11/imm32/alloc-id:fake
30650     Int-var-and-literal/imm32/inouts
30651     0/imm32/no-outputs
30652     0/imm32/no-outputs
30653     0x11/imm32/alloc-id:fake
30654     _string_81_subop_and/imm32/subx-name
30655     1/imm32/rm32-is-first-inout
30656     0/imm32/no-r32
30657     2/imm32/imm32-is-second-inout
30658     0/imm32/no-imm8
30659     0/imm32/no-disp32
30660     0/imm32/no-xm32
30661     0/imm32/no-x32
30662     0x11/imm32/alloc-id:fake
30663     _Primitive-or-with-eax/imm32/next
30664 # - or
30665 _Primitive-or-with-eax:  # (payload primitive)
30666     0x11/imm32/alloc-id:fake:payload
30667     # var/eax <- or lit => 0d/or-with-eax lit/imm32
30668     0x11/imm32/alloc-id:fake
30669     _string-or/imm32/name
30670     0x11/imm32/alloc-id:fake
30671     Single-lit-var/imm32/inouts
30672     0x11/imm32/alloc-id:fake
30673     Single-int-var-in-eax/imm32/outputs
30674     0x11/imm32/alloc-id:fake
30675     _string_0d_or_with_eax/imm32/subx-name
30676     0/imm32/no-rm32
30677     0/imm32/no-r32
30678     1/imm32/imm32-is-first-inout
30679     0/imm32/no-imm8
30680     0/imm32/no-disp32
30681     0/imm32/no-xm32
30682     0/imm32/no-x32
30683     0x11/imm32/alloc-id:fake
30684     _Primitive-or-reg-with-reg/imm32/next
30685 _Primitive-or-reg-with-reg:  # (payload primitive)
30686     0x11/imm32/alloc-id:fake:payload
30687     # var1/reg <- or var2/reg => 09/or-with var1/rm32 var2/r32
30688     0x11/imm32/alloc-id:fake
30689     _string-or/imm32/name
30690     0x11/imm32/alloc-id:fake
30691     Single-int-var-in-some-register/imm32/inouts
30692     0x11/imm32/alloc-id:fake
30693     Single-int-var-in-some-register/imm32/outputs
30694     0x11/imm32/alloc-id:fake
30695     _string_09_or_with/imm32/subx-name
30696     3/imm32/rm32-is-first-output
30697     1/imm32/r32-is-first-inout
30698     0/imm32/no-imm32
30699     0/imm32/no-imm8
30700     0/imm32/no-disp32
30701     0/imm32/no-xm32
30702     0/imm32/no-x32
30703     0x11/imm32/alloc-id:fake
30704     _Primitive-or-reg-with-mem/imm32/next
30705 _Primitive-or-reg-with-mem:  # (payload primitive)
30706     0x11/imm32/alloc-id:fake:payload
30707     # or-with var1 var2/reg => 09/or-with var1 var2/r32
30708     0x11/imm32/alloc-id:fake
30709     _string-or-with/imm32/name
30710     0x11/imm32/alloc-id:fake
30711     Two-args-int-stack-int-reg/imm32/inouts
30712     0/imm32/no-outputs
30713     0/imm32/no-outputs
30714     0x11/imm32/alloc-id:fake
30715     _string_09_or_with/imm32/subx-name
30716     1/imm32/rm32-is-first-inout
30717     2/imm32/r32-is-second-inout
30718     0/imm32/no-imm32
30719     0/imm32/no-imm8
30720     0/imm32/no-disp32
30721     0/imm32/no-xm32
30722     0/imm32/no-x32
30723     0x11/imm32/alloc-id:fake
30724     _Primitive-or-mem-with-reg/imm32/next
30725 _Primitive-or-mem-with-reg:  # (payload primitive)
30726     0x11/imm32/alloc-id:fake:payload
30727     # var1/reg <- or var2 => 0b/or var2/rm32 var1/r32
30728     0x11/imm32/alloc-id:fake
30729     _string-or/imm32/name
30730     0x11/imm32/alloc-id:fake
30731     Single-int-var-in-mem/imm32/inouts
30732     0x11/imm32/alloc-id:fake
30733     Single-int-var-in-some-register/imm32/outputs
30734     0x11/imm32/alloc-id:fake
30735     _string_0b_or/imm32/subx-name
30736     1/imm32/rm32-is-first-inout
30737     3/imm32/r32-is-first-output
30738     0/imm32/no-imm32
30739     0/imm32/no-imm8
30740     0/imm32/no-disp32
30741     0/imm32/no-xm32
30742     0/imm32/no-x32
30743     0x11/imm32/alloc-id:fake
30744     _Primitive-or-lit-with-reg/imm32/next
30745 _Primitive-or-lit-with-reg:  # (payload primitive)
30746     0x11/imm32/alloc-id:fake:payload
30747     # var1/reg <- or lit => 81 1/subop/or var1/rm32 lit/imm32
30748     0x11/imm32/alloc-id:fake
30749     _string-or/imm32/name
30750     0x11/imm32/alloc-id:fake
30751     Single-lit-var/imm32/inouts
30752     0x11/imm32/alloc-id:fake
30753     Single-int-var-in-some-register/imm32/outputs
30754     0x11/imm32/alloc-id:fake
30755     _string_81_subop_or/imm32/subx-name
30756     3/imm32/rm32-is-first-output
30757     0/imm32/no-r32
30758     1/imm32/imm32-is-first-inout
30759     0/imm32/no-imm8
30760     0/imm32/no-disp32
30761     0/imm32/no-xm32
30762     0/imm32/no-x32
30763     0x11/imm32/alloc-id:fake
30764     _Primitive-or-lit-with-mem/imm32/next
30765 _Primitive-or-lit-with-mem:  # (payload primitive)
30766     0x11/imm32/alloc-id:fake:payload
30767     # or-with var1, lit => 81 1/subop/or var1/rm32 lit/imm32
30768     0x11/imm32/alloc-id:fake
30769     _string-or-with/imm32/name
30770     0x11/imm32/alloc-id:fake
30771     Int-var-and-literal/imm32/inouts
30772     0/imm32/no-outputs
30773     0/imm32/no-outputs
30774     0x11/imm32/alloc-id:fake
30775     _string_81_subop_or/imm32/subx-name
30776     1/imm32/rm32-is-first-inout
30777     0/imm32/no-r32
30778     2/imm32/imm32-is-second-inout
30779     0/imm32/no-imm8
30780     0/imm32/no-disp32
30781     0/imm32/no-xm32
30782     0/imm32/no-x32
30783     0x11/imm32/alloc-id:fake
30784     _Primitive-xor-with-eax/imm32/next
30785 # - xor
30786 _Primitive-xor-with-eax:  # (payload primitive)
30787     0x11/imm32/alloc-id:fake:payload
30788     # var/eax <- xor lit => 35/xor-with-eax lit/imm32
30789     0x11/imm32/alloc-id:fake
30790     _string-xor/imm32/name
30791     0x11/imm32/alloc-id:fake
30792     Single-lit-var/imm32/inouts
30793     0x11/imm32/alloc-id:fake
30794     Single-int-var-in-eax/imm32/outputs
30795     0x11/imm32/alloc-id:fake
30796     _string_35_xor_with_eax/imm32/subx-name
30797     0/imm32/no-rm32
30798     0/imm32/no-r32
30799     1/imm32/imm32-is-first-inout
30800     0/imm32/no-imm8
30801     0/imm32/no-disp32
30802     0/imm32/no-xm32
30803     0/imm32/no-x32
30804     0x11/imm32/alloc-id:fake
30805     _Primitive-xor-reg-with-reg/imm32/next
30806 _Primitive-xor-reg-with-reg:  # (payload primitive)
30807     0x11/imm32/alloc-id:fake:payload
30808     # var1/reg <- xor var2/reg => 31/xor-with var1/rm32 var2/r32
30809     0x11/imm32/alloc-id:fake
30810     _string-xor/imm32/name
30811     0x11/imm32/alloc-id:fake
30812     Single-int-var-in-some-register/imm32/inouts
30813     0x11/imm32/alloc-id:fake
30814     Single-int-var-in-some-register/imm32/outputs
30815     0x11/imm32/alloc-id:fake
30816     _string_31_xor_with/imm32/subx-name
30817     3/imm32/rm32-is-first-output
30818     1/imm32/r32-is-first-inout
30819     0/imm32/no-imm32
30820     0/imm32/no-imm8
30821     0/imm32/no-disp32
30822     0/imm32/no-xm32
30823     0/imm32/no-x32
30824     0x11/imm32/alloc-id:fake
30825     _Primitive-xor-reg-with-mem/imm32/next
30826 _Primitive-xor-reg-with-mem:  # (payload primitive)
30827     0x11/imm32/alloc-id:fake:payload
30828     # xor-with var1 var2/reg => 31/xor-with var1 var2/r32
30829     0x11/imm32/alloc-id:fake
30830     _string-xor-with/imm32/name
30831     0x11/imm32/alloc-id:fake
30832     Two-args-int-stack-int-reg/imm32/inouts
30833     0/imm32/no-outputs
30834     0/imm32/no-outputs
30835     0x11/imm32/alloc-id:fake
30836     _string_31_xor_with/imm32/subx-name
30837     1/imm32/rm32-is-first-inout
30838     2/imm32/r32-is-second-inout
30839     0/imm32/no-imm32
30840     0/imm32/no-imm8
30841     0/imm32/no-disp32
30842     0/imm32/no-xm32
30843     0/imm32/no-x32
30844     0x11/imm32/alloc-id:fake
30845     _Primitive-xor-mem-with-reg/imm32/next
30846 _Primitive-xor-mem-with-reg:  # (payload primitive)
30847     0x11/imm32/alloc-id:fake:payload
30848     # var1/reg <- xor var2 => 33/xor var2/rm32 var1/r32
30849     0x11/imm32/alloc-id:fake
30850     _string-xor/imm32/name
30851     0x11/imm32/alloc-id:fake
30852     Single-int-var-in-mem/imm32/inouts
30853     0x11/imm32/alloc-id:fake
30854     Single-int-var-in-some-register/imm32/outputs
30855     0x11/imm32/alloc-id:fake
30856     _string_33_xor/imm32/subx-name
30857     1/imm32/rm32-is-first-inout
30858     3/imm32/r32-is-first-output
30859     0/imm32/no-imm32
30860     0/imm32/no-imm8
30861     0/imm32/no-disp32
30862     0/imm32/no-xm32
30863     0/imm32/no-x32
30864     0x11/imm32/alloc-id:fake
30865     _Primitive-xor-lit-with-reg/imm32/next
30866 _Primitive-xor-lit-with-reg:  # (payload primitive)
30867     0x11/imm32/alloc-id:fake:payload
30868     # var1/reg <- xor lit => 81 6/subop/xor var1/rm32 lit/imm32
30869     0x11/imm32/alloc-id:fake
30870     _string-xor/imm32/name
30871     0x11/imm32/alloc-id:fake
30872     Single-lit-var/imm32/inouts
30873     0x11/imm32/alloc-id:fake
30874     Single-int-var-in-some-register/imm32/outputs
30875     0x11/imm32/alloc-id:fake
30876     _string_81_subop_xor/imm32/subx-name
30877     3/imm32/rm32-is-first-output
30878     0/imm32/no-r32
30879     1/imm32/imm32-is-first-inout
30880     0/imm32/no-imm8
30881     0/imm32/no-disp32
30882     0/imm32/no-xm32
30883     0/imm32/no-x32
30884     0x11/imm32/alloc-id:fake
30885     _Primitive-xor-lit-with-mem/imm32/next
30886 _Primitive-xor-lit-with-mem:  # (payload primitive)
30887     0x11/imm32/alloc-id:fake:payload
30888     # xor-with var1, lit => 81 6/subop/xor var1/rm32 lit/imm32
30889     0x11/imm32/alloc-id:fake
30890     _string-xor-with/imm32/name
30891     0x11/imm32/alloc-id:fake
30892     Int-var-and-literal/imm32/inouts
30893     0/imm32/no-outputs
30894     0/imm32/no-outputs
30895     0x11/imm32/alloc-id:fake
30896     _string_81_subop_xor/imm32/subx-name
30897     1/imm32/rm32-is-first-inout
30898     0/imm32/no-r32
30899     2/imm32/imm32-is-second-inout
30900     0/imm32/no-imm8
30901     0/imm32/no-disp32
30902     0/imm32/no-xm32
30903     0/imm32/no-x32
30904     0x11/imm32/alloc-id:fake
30905     _Primitive-shift-reg-left-by-lit/imm32/next
30906 _Primitive-shift-reg-left-by-lit:  # (payload primitive)
30907     0x11/imm32/alloc-id:fake:payload
30908     # var1/reg <- shift-left lit => c1/shift 4/subop/left var1/rm32 lit/imm32
30909     0x11/imm32/alloc-id:fake
30910     _string-shift-left/imm32/name
30911     0x11/imm32/alloc-id:fake
30912     Single-lit-var/imm32/inouts
30913     0x11/imm32/alloc-id:fake
30914     Single-int-var-in-some-register/imm32/outputs
30915     0x11/imm32/alloc-id:fake
30916     _string_c1_subop_shift_left/imm32/subx-name
30917     3/imm32/rm32-is-first-output
30918     0/imm32/no-r32
30919     0/imm32/no-imm32
30920     1/imm32/imm8-is-first-inout
30921     0/imm32/no-disp32
30922     0/imm32/no-xm32
30923     0/imm32/no-x32
30924     0x11/imm32/alloc-id:fake
30925     _Primitive-shift-reg-right-by-lit/imm32/next
30926 _Primitive-shift-reg-right-by-lit:  # (payload primitive)
30927     0x11/imm32/alloc-id:fake:payload
30928     # var1/reg <- shift-right lit => c1/shift 5/subop/right var1/rm32 lit/imm32
30929     0x11/imm32/alloc-id:fake
30930     _string-shift-right/imm32/name
30931     0x11/imm32/alloc-id:fake
30932     Single-lit-var/imm32/inouts
30933     0x11/imm32/alloc-id:fake
30934     Single-int-var-in-some-register/imm32/outputs
30935     0x11/imm32/alloc-id:fake
30936     _string_c1_subop_shift_right_padding_zeroes/imm32/subx-name
30937     3/imm32/rm32-is-first-output
30938     0/imm32/no-r32
30939     0/imm32/no-imm32
30940     1/imm32/imm8-is-first-inout
30941     0/imm32/no-disp32
30942     0/imm32/no-xm32
30943     0/imm32/no-x32
30944     0x11/imm32/alloc-id:fake
30945     _Primitive-shift-reg-right-signed-by-lit/imm32/next
30946 _Primitive-shift-reg-right-signed-by-lit:  # (payload primitive)
30947     0x11/imm32/alloc-id:fake:payload
30948     # var1/reg <- shift-right-signed lit => c1/shift 7/subop/right-preserving-sign var1/rm32 lit/imm32
30949     0x11/imm32/alloc-id:fake
30950     _string-shift-right-signed/imm32/name
30951     0x11/imm32/alloc-id:fake
30952     Single-lit-var/imm32/inouts
30953     0x11/imm32/alloc-id:fake
30954     Single-int-var-in-some-register/imm32/outputs
30955     0x11/imm32/alloc-id:fake
30956     _string_c1_subop_shift_right_preserving_sign/imm32/subx-name
30957     3/imm32/rm32-is-first-output
30958     0/imm32/no-r32
30959     0/imm32/no-imm32
30960     1/imm32/imm8-is-first-inout
30961     0/imm32/no-disp32
30962     0/imm32/no-xm32
30963     0/imm32/no-x32
30964     0x11/imm32/alloc-id:fake
30965     _Primitive-shift-mem-left-by-lit/imm32/next
30966 _Primitive-shift-mem-left-by-lit:  # (payload primitive)
30967     0x11/imm32/alloc-id:fake:payload
30968     # shift-left var1, lit => c1/shift 4/subop/left var1/rm32 lit/imm32
30969     0x11/imm32/alloc-id:fake
30970     _string-shift-left/imm32/name
30971     0x11/imm32/alloc-id:fake
30972     Int-var-and-literal/imm32/inouts
30973     0/imm32/no-outputs
30974     0/imm32/no-outputs
30975     0x11/imm32/alloc-id:fake
30976     _string_c1_subop_shift_left/imm32/subx-name
30977     1/imm32/rm32-is-first-inout
30978     0/imm32/no-r32
30979     0/imm32/no-imm32
30980     2/imm32/imm8-is-second-inout
30981     0/imm32/no-disp32
30982     0/imm32/no-xm32
30983     0/imm32/no-x32
30984     0x11/imm32/alloc-id:fake
30985     _Primitive-shift-mem-right-by-lit/imm32/next
30986 _Primitive-shift-mem-right-by-lit:  # (payload primitive)
30987     0x11/imm32/alloc-id:fake:payload
30988     # shift-right var1, lit => c1/shift 5/subop/right var1/rm32 lit/imm32
30989     0x11/imm32/alloc-id:fake
30990     _string-shift-right/imm32/name
30991     0x11/imm32/alloc-id:fake
30992     Int-var-and-literal/imm32/inouts
30993     0/imm32/no-outputs
30994     0/imm32/no-outputs
30995     0x11/imm32/alloc-id:fake
30996     _string_c1_subop_shift_right_padding_zeroes/imm32/subx-name
30997     1/imm32/rm32-is-first-inout
30998     0/imm32/no-r32
30999     0/imm32/no-imm32
31000     2/imm32/imm8-is-second-inout
31001     0/imm32/no-disp32
31002     0/imm32/no-xm32
31003     0/imm32/no-x32
31004     0x11/imm32/alloc-id:fake
31005     _Primitive-shift-mem-right-signed-by-lit/imm32/next
31006 _Primitive-shift-mem-right-signed-by-lit:  # (payload primitive)
31007     0x11/imm32/alloc-id:fake:payload
31008     # shift-right-signed var1, lit => c1/shift 7/subop/right-preserving-sign var1/rm32 lit/imm32
31009     0x11/imm32/alloc-id:fake
31010     _string-shift-right-signed/imm32/name
31011     0x11/imm32/alloc-id:fake
31012     Int-var-and-literal/imm32/inouts
31013     0/imm32/no-outputs
31014     0/imm32/no-outputs
31015     0x11/imm32/alloc-id:fake
31016     _string_c1_subop_shift_right_preserving_sign/imm32/subx-name
31017     1/imm32/rm32-is-first-inout
31018     0/imm32/no-r32
31019     0/imm32/no-imm32
31020     2/imm32/imm8-is-second-inout
31021     0/imm32/no-disp32
31022     0/imm32/no-xm32
31023     0/imm32/no-x32
31024     0x11/imm32/alloc-id:fake
31025     _Primitive-copy-to-eax/imm32/next
31026 # - copy
31027 _Primitive-copy-to-eax:  # (payload primitive)
31028     0x11/imm32/alloc-id:fake:payload
31029     # var/eax <- copy lit => b8/copy-to-eax lit/imm32
31030     0x11/imm32/alloc-id:fake
31031     _string-copy/imm32/name
31032     0x11/imm32/alloc-id:fake
31033     Single-lit-var/imm32/inouts
31034     0x11/imm32/alloc-id:fake
31035     Single-int-var-in-eax/imm32/outputs
31036     0x11/imm32/alloc-id:fake
31037     _string_b8_copy_to_eax/imm32/subx-name
31038     0/imm32/no-rm32
31039     0/imm32/no-r32
31040     1/imm32/imm32-is-first-inout
31041     0/imm32/no-imm8
31042     0/imm32/no-disp32
31043     0/imm32/no-xm32
31044     0/imm32/no-x32
31045     0x11/imm32/alloc-id:fake
31046     _Primitive-copy-to-ecx/imm32/next
31047 _Primitive-copy-to-ecx:  # (payload primitive)
31048     0x11/imm32/alloc-id:fake:payload
31049     # var/ecx <- copy lit => b9/copy-to-ecx lit/imm32
31050     0x11/imm32/alloc-id:fake
31051     _string-copy/imm32/name
31052     0x11/imm32/alloc-id:fake
31053     Single-lit-var/imm32/inouts
31054     0x11/imm32/alloc-id:fake
31055     Single-int-var-in-ecx/imm32/outputs
31056     0x11/imm32/alloc-id:fake
31057     _string_b9_copy_to_ecx/imm32/subx-name
31058     0/imm32/no-rm32
31059     0/imm32/no-r32
31060     1/imm32/imm32-is-first-inout
31061     0/imm32/no-imm8
31062     0/imm32/no-disp32
31063     0/imm32/no-xm32
31064     0/imm32/no-x32
31065     0x11/imm32/alloc-id:fake
31066     _Primitive-copy-to-edx/imm32/next
31067 _Primitive-copy-to-edx:  # (payload primitive)
31068     0x11/imm32/alloc-id:fake:payload
31069     # var/edx <- copy lit => ba/copy-to-edx lit/imm32
31070     0x11/imm32/alloc-id:fake
31071     _string-copy/imm32/name
31072     0x11/imm32/alloc-id:fake
31073     Single-lit-var/imm32/inouts
31074     0x11/imm32/alloc-id:fake
31075     Single-int-var-in-edx/imm32/outputs
31076     0x11/imm32/alloc-id:fake
31077     _string_ba_copy_to_edx/imm32/subx-name
31078     0/imm32/no-rm32
31079     0/imm32/no-r32
31080     1/imm32/imm32-is-first-inout
31081     0/imm32/no-imm8
31082     0/imm32/no-disp32
31083     0/imm32/no-xm32
31084     0/imm32/no-x32
31085     0x11/imm32/alloc-id:fake
31086     _Primitive-copy-to-ebx/imm32/next
31087 _Primitive-copy-to-ebx:  # (payload primitive)
31088     0x11/imm32/alloc-id:fake:payload
31089     # var/ebx <- copy lit => bb/copy-to-ebx lit/imm32
31090     0x11/imm32/alloc-id:fake
31091     _string-copy/imm32/name
31092     0x11/imm32/alloc-id:fake
31093     Single-lit-var/imm32/inouts
31094     0x11/imm32/alloc-id:fake
31095     Single-int-var-in-ebx/imm32/outputs
31096     0x11/imm32/alloc-id:fake
31097     _string_bb_copy_to_ebx/imm32/subx-name
31098     0/imm32/no-rm32
31099     0/imm32/no-r32
31100     1/imm32/imm32-is-first-inout
31101     0/imm32/no-imm8
31102     0/imm32/no-disp32
31103     0/imm32/no-xm32
31104     0/imm32/no-x32
31105     0x11/imm32/alloc-id:fake
31106     _Primitive-copy-to-esi/imm32/next
31107 _Primitive-copy-to-esi:  # (payload primitive)
31108     0x11/imm32/alloc-id:fake:payload
31109     # var/esi <- copy lit => be/copy-to-esi lit/imm32
31110     0x11/imm32/alloc-id:fake
31111     _string-copy/imm32/name
31112     0x11/imm32/alloc-id:fake
31113     Single-lit-var/imm32/inouts
31114     0x11/imm32/alloc-id:fake
31115     Single-int-var-in-esi/imm32/outputs
31116     0x11/imm32/alloc-id:fake
31117     _string_be_copy_to_esi/imm32/subx-name
31118     0/imm32/no-rm32
31119     0/imm32/no-r32
31120     1/imm32/imm32-is-first-inout
31121     0/imm32/no-imm8
31122     0/imm32/no-disp32
31123     0/imm32/no-xm32
31124     0/imm32/no-x32
31125     0x11/imm32/alloc-id:fake
31126     _Primitive-copy-to-edi/imm32/next
31127 _Primitive-copy-to-edi:  # (payload primitive)
31128     0x11/imm32/alloc-id:fake:payload
31129     # var/edi <- copy lit => bf/copy-to-edi lit/imm32
31130     0x11/imm32/alloc-id:fake
31131     _string-copy/imm32/name
31132     0x11/imm32/alloc-id:fake
31133     Single-lit-var/imm32/inouts
31134     0x11/imm32/alloc-id:fake
31135     Single-int-var-in-edi/imm32/outputs
31136     0x11/imm32/alloc-id:fake
31137     _string_bf_copy_to_edi/imm32/subx-name
31138     0/imm32/no-rm32
31139     0/imm32/no-r32
31140     1/imm32/imm32-is-first-inout
31141     0/imm32/no-imm8
31142     0/imm32/no-disp32
31143     0/imm32/no-xm32
31144     0/imm32/no-x32
31145     0x11/imm32/alloc-id:fake
31146     _Primitive-copy-reg-to-reg/imm32/next
31147 _Primitive-copy-reg-to-reg:  # (payload primitive)
31148     0x11/imm32/alloc-id:fake:payload
31149     # var1/reg <- copy var2/reg => 89/<- var1/rm32 var2/r32
31150     0x11/imm32/alloc-id:fake
31151     _string-copy/imm32/name
31152     0x11/imm32/alloc-id:fake
31153     Single-int-var-in-some-register/imm32/inouts
31154     0x11/imm32/alloc-id:fake
31155     Single-int-var-in-some-register/imm32/outputs
31156     0x11/imm32/alloc-id:fake
31157     _string_89_<-/imm32/subx-name
31158     3/imm32/rm32-is-first-output
31159     1/imm32/r32-is-first-inout
31160     0/imm32/no-imm32
31161     0/imm32/no-imm8
31162     0/imm32/no-disp32
31163     0/imm32/no-xm32
31164     0/imm32/no-x32
31165     0x11/imm32/alloc-id:fake
31166     _Primitive-copy-reg-to-mem/imm32/next
31167 _Primitive-copy-reg-to-mem:  # (payload primitive)
31168     0x11/imm32/alloc-id:fake:payload
31169     # copy-to var1 var2/reg => 89/<- var1 var2/r32
31170     0x11/imm32/alloc-id:fake
31171     _string-copy-to/imm32/name
31172     0x11/imm32/alloc-id:fake
31173     Two-args-int-stack-int-reg/imm32/inouts
31174     0/imm32/no-outputs
31175     0/imm32/no-outputs
31176     0x11/imm32/alloc-id:fake
31177     _string_89_<-/imm32/subx-name
31178     1/imm32/rm32-is-first-inout
31179     2/imm32/r32-is-second-inout
31180     0/imm32/no-imm32
31181     0/imm32/no-imm8
31182     0/imm32/no-disp32
31183     0/imm32/no-xm32
31184     0/imm32/no-x32
31185     0x11/imm32/alloc-id:fake
31186     _Primitive-copy-mem-to-reg/imm32/next
31187 _Primitive-copy-mem-to-reg:  # (payload primitive)
31188     0x11/imm32/alloc-id:fake:payload
31189     # var1/reg <- copy var2 => 8b/-> var2/rm32 var1/r32
31190     0x11/imm32/alloc-id:fake
31191     _string-copy/imm32/name
31192     0x11/imm32/alloc-id:fake
31193     Single-int-var-in-mem/imm32/inouts
31194     0x11/imm32/alloc-id:fake
31195     Single-int-var-in-some-register/imm32/outputs
31196     0x11/imm32/alloc-id:fake
31197     _string_8b_->/imm32/subx-name
31198     1/imm32/rm32-is-first-inout
31199     3/imm32/r32-is-first-output
31200     0/imm32/no-imm32
31201     0/imm32/no-imm8
31202     0/imm32/no-disp32
31203     0/imm32/no-xm32
31204     0/imm32/no-x32
31205     0x11/imm32/alloc-id:fake
31206     _Primitive-copy-lit-to-reg/imm32/next
31207 _Primitive-copy-lit-to-reg:  # (payload primitive)
31208     0x11/imm32/alloc-id:fake:payload
31209     # var1/reg <- copy lit => c7 0/subop/copy var1/rm32 lit/imm32
31210     0x11/imm32/alloc-id:fake
31211     _string-copy/imm32/name
31212     0x11/imm32/alloc-id:fake
31213     Single-lit-var/imm32/inouts
31214     0x11/imm32/alloc-id:fake
31215     Single-int-var-in-some-register/imm32/outputs
31216     0x11/imm32/alloc-id:fake
31217     _string_c7_subop_copy/imm32/subx-name
31218     3/imm32/rm32-is-first-output
31219     0/imm32/no-r32
31220     1/imm32/imm32-is-first-inout
31221     0/imm32/no-imm8
31222     0/imm32/no-disp32
31223     0/imm32/no-xm32
31224     0/imm32/no-x32
31225     0x11/imm32/alloc-id:fake
31226     _Primitive-copy-lit-to-mem/imm32/next
31227 _Primitive-copy-lit-to-mem:  # (payload primitive)
31228     0x11/imm32/alloc-id:fake:payload
31229     # copy-to var1, lit => c7 0/subop/copy var1/rm32 lit/imm32
31230     0x11/imm32/alloc-id:fake
31231     _string-copy-to/imm32/name
31232     0x11/imm32/alloc-id:fake
31233     Int-var-and-literal/imm32/inouts
31234     0/imm32/no-outputs
31235     0/imm32/no-outputs
31236     0x11/imm32/alloc-id:fake
31237     _string_c7_subop_copy/imm32/subx-name
31238     1/imm32/rm32-is-first-inout
31239     0/imm32/no-r32
31240     2/imm32/imm32-is-second-inout
31241     0/imm32/no-imm8
31242     0/imm32/no-disp32
31243     0/imm32/no-xm32
31244     0/imm32/no-x32
31245     0x11/imm32/alloc-id:fake
31246     _Primitive-copy-byte-from-reg/imm32/next
31247 # - copy byte
31248 _Primitive-copy-byte-from-reg:
31249     0x11/imm32/alloc-id:fake:payload
31250     # var/reg <- copy-byte var2/reg2 => 8a/byte-> %var2 var/r32
31251     0x11/imm32/alloc-id:fake
31252     _string-copy-byte/imm32/name
31253     0x11/imm32/alloc-id:fake
31254     Single-byte-var-in-some-register/imm32/inouts
31255     0x11/imm32/alloc-id:fake
31256     Single-byte-var-in-some-register/imm32/outputs
31257     0x11/imm32/alloc-id:fake
31258     _string_8a_copy_byte/imm32/subx-name
31259     1/imm32/rm32-is-first-inout
31260     3/imm32/r32-is-first-output
31261     0/imm32/no-imm32
31262     0/imm32/no-imm8
31263     0/imm32/no-disp32
31264     0/imm32/no-xm32
31265     0/imm32/no-x32
31266     0x11/imm32/alloc-id:fake
31267     _Primitive-copy-byte-from-mem/imm32/next
31268 _Primitive-copy-byte-from-mem:
31269     0x11/imm32/alloc-id:fake:payload
31270     # var/reg <- copy-byte *var2/reg2 => 8a/byte-> *var2 var/r32
31271     0x11/imm32/alloc-id:fake
31272     _string-copy-byte/imm32/name
31273     0x11/imm32/alloc-id:fake
31274     Single-byte-var-in-mem/imm32/inouts
31275     0x11/imm32/alloc-id:fake
31276     Single-byte-var-in-some-register/imm32/outputs
31277     0x11/imm32/alloc-id:fake
31278     _string_8a_copy_byte/imm32/subx-name
31279     1/imm32/rm32-is-first-inout
31280     3/imm32/r32-is-first-output
31281     0/imm32/no-imm32
31282     0/imm32/no-imm8
31283     0/imm32/no-disp32
31284     0/imm32/no-xm32
31285     0/imm32/no-x32
31286     0x11/imm32/alloc-id:fake
31287     _Primitive-copy-byte-to-mem/imm32/next
31288 _Primitive-copy-byte-to-mem:
31289     0x11/imm32/alloc-id:fake:payload
31290     # copy-byte-to *var1/reg1, var2/reg2 => 88/byte<- *reg1 reg2/r32
31291     0x11/imm32/alloc-id:fake
31292     _string-copy-byte-to/imm32/name
31293     0x11/imm32/alloc-id:fake
31294     Two-args-byte-stack-byte-reg/imm32/inouts
31295     0/imm32/no-outputs
31296     0/imm32/no-outputs
31297     0x11/imm32/alloc-id:fake
31298     _string_88_copy_byte/imm32/subx-name
31299     1/imm32/rm32-is-first-inout
31300     2/imm32/r32-is-second-inout
31301     0/imm32/no-imm32
31302     0/imm32/no-imm8
31303     0/imm32/no-disp32
31304     0/imm32/no-xm32
31305     0/imm32/no-x32
31306     0x11/imm32/alloc-id:fake
31307     _Primitive-address/imm32/next
31308 # - address
31309 _Primitive-address:  # (payload primitive)
31310     0x11/imm32/alloc-id:fake:payload
31311     # var1/reg <- address var2 => 8d/copy-address var2/rm32 var1/r32
31312     0x11/imm32/alloc-id:fake
31313     _string-address/imm32/name
31314     0x11/imm32/alloc-id:fake
31315     Single-int-var-in-mem/imm32/inouts
31316     0x11/imm32/alloc-id:fake
31317     Single-addr-var-in-some-register/imm32/outputs
31318     0x11/imm32/alloc-id:fake
31319     _string_8d_copy_address/imm32/subx-name
31320     1/imm32/rm32-is-first-inout
31321     3/imm32/r32-is-first-output
31322     0/imm32/no-imm32
31323     0/imm32/no-imm8
31324     0/imm32/no-disp32
31325     0/imm32/no-xm32
31326     0/imm32/no-x32
31327     0x11/imm32/alloc-id:fake
31328     _Primitive-compare-reg-with-reg/imm32/next
31329 # - compare
31330 _Primitive-compare-reg-with-reg:  # (payload primitive)
31331     0x11/imm32/alloc-id:fake:payload
31332     # compare var1/reg1 var2/reg2 => 39/compare var1/rm32 var2/r32
31333     0x11/imm32/alloc-id:fake
31334     _string-compare/imm32/name
31335     0x11/imm32/alloc-id:fake
31336     Two-int-args-in-regs/imm32/inouts
31337     0/imm32/no-outputs
31338     0/imm32/no-outputs
31339     0x11/imm32/alloc-id:fake
31340     _string_39_compare->/imm32/subx-name
31341     1/imm32/rm32-is-first-inout
31342     2/imm32/r32-is-second-inout
31343     0/imm32/no-imm32
31344     0/imm32/no-imm8
31345     0/imm32/no-disp32
31346     0/imm32/no-xm32
31347     0/imm32/no-x32
31348     0x11/imm32/alloc-id:fake
31349     _Primitive-compare-mem-with-reg/imm32/next
31350 _Primitive-compare-mem-with-reg:  # (payload primitive)
31351     0x11/imm32/alloc-id:fake:payload
31352     # compare var1 var2/reg => 39/compare var1/rm32 var2/r32
31353     0x11/imm32/alloc-id:fake
31354     _string-compare/imm32/name
31355     0x11/imm32/alloc-id:fake
31356     Two-args-int-stack-int-reg/imm32/inouts
31357     0/imm32/no-outputs
31358     0/imm32/no-outputs
31359     0x11/imm32/alloc-id:fake
31360     _string_39_compare->/imm32/subx-name
31361     1/imm32/rm32-is-first-inout
31362     2/imm32/r32-is-second-inout
31363     0/imm32/no-imm32
31364     0/imm32/no-imm8
31365     0/imm32/no-disp32
31366     0/imm32/no-xm32
31367     0/imm32/no-x32
31368     0x11/imm32/alloc-id:fake
31369     _Primitive-compare-reg-with-mem/imm32/next
31370 _Primitive-compare-reg-with-mem:  # (payload primitive)
31371     0x11/imm32/alloc-id:fake:payload
31372     # compare var1/reg var2 => 3b/compare<- var2/rm32 var1/r32
31373     0x11/imm32/alloc-id:fake
31374     _string-compare/imm32/name
31375     0x11/imm32/alloc-id:fake
31376     Two-args-int-reg-int-stack/imm32/inouts
31377     0/imm32/no-outputs
31378     0/imm32/no-outputs
31379     0x11/imm32/alloc-id:fake
31380     _string_3b_compare<-/imm32/subx-name
31381     2/imm32/rm32-is-second-inout
31382     1/imm32/r32-is-first-inout
31383     0/imm32/no-imm32
31384     0/imm32/no-imm8
31385     0/imm32/no-disp32
31386     0/imm32/no-xm32
31387     0/imm32/no-x32
31388     0x11/imm32/alloc-id:fake
31389     _Primitive-compare-eax-with-literal/imm32/next
31390 _Primitive-compare-eax-with-literal:  # (payload primitive)
31391     0x11/imm32/alloc-id:fake:payload
31392     # compare var1/eax n => 3d/compare-eax-with n/imm32
31393     0x11/imm32/alloc-id:fake
31394     _string-compare/imm32/name
31395     0x11/imm32/alloc-id:fake
31396     Two-args-int-eax-int-literal/imm32/inouts
31397     0/imm32/no-outputs
31398     0/imm32/no-outputs
31399     0x11/imm32/alloc-id:fake
31400     _string_3d_compare_eax_with/imm32/subx-name
31401     0/imm32/no-rm32
31402     0/imm32/no-r32
31403     2/imm32/imm32-is-second-inout
31404     0/imm32/no-imm8
31405     0/imm32/no-disp32
31406     0/imm32/no-xm32
31407     0/imm32/no-x32
31408     0x11/imm32/alloc-id:fake
31409     _Primitive-compare-reg-with-literal/imm32/next
31410 _Primitive-compare-reg-with-literal:  # (payload primitive)
31411     0x11/imm32/alloc-id:fake:payload
31412     # compare var1/reg n => 81 7/subop/compare %reg n/imm32
31413     0x11/imm32/alloc-id:fake
31414     _string-compare/imm32/name
31415     0x11/imm32/alloc-id:fake
31416     Int-var-in-register-and-literal/imm32/inouts
31417     0/imm32/no-outputs
31418     0/imm32/no-outputs
31419     0x11/imm32/alloc-id:fake
31420     _string_81_subop_compare/imm32/subx-name
31421     1/imm32/rm32-is-first-inout
31422     0/imm32/no-r32
31423     2/imm32/imm32-is-second-inout
31424     0/imm32/no-imm8
31425     0/imm32/no-disp32
31426     0/imm32/no-xm32
31427     0/imm32/no-x32
31428     0x11/imm32/alloc-id:fake
31429     _Primitive-compare-mem-with-literal/imm32/next
31430 _Primitive-compare-mem-with-literal:  # (payload primitive)
31431     0x11/imm32/alloc-id:fake:payload
31432     # compare var1 n => 81 7/subop/compare *(ebp+___) n/imm32
31433     0x11/imm32/alloc-id:fake
31434     _string-compare/imm32/name
31435     0x11/imm32/alloc-id:fake
31436     Int-var-and-literal/imm32/inouts
31437     0/imm32/no-outputs
31438     0/imm32/no-outputs
31439     0x11/imm32/alloc-id:fake
31440     _string_81_subop_compare/imm32/subx-name
31441     1/imm32/rm32-is-first-inout
31442     0/imm32/no-r32
31443     2/imm32/imm32-is-second-inout
31444     0/imm32/no-imm8
31445     0/imm32/no-disp32
31446     0/imm32/no-xm32
31447     0/imm32/no-x32
31448     0x11/imm32/alloc-id:fake
31449     _Primitive-negate-reg/imm32/next
31450 # - negate
31451 _Primitive-negate-reg:  # (payload primitive)
31452     0x11/imm32/alloc-id:fake:payload
31453     # var1/reg <- negate => f7 3/subop/negate var1/rm32
31454     0x11/imm32/alloc-id:fake
31455     _string-negate/imm32/name
31456     0/imm32/no-inouts
31457     0/imm32/no-inouts
31458     0x11/imm32/alloc-id:fake
31459     Single-int-var-in-some-register/imm32/outputs
31460     0x11/imm32/alloc-id:fake
31461     _string_f7_subop_negate/imm32/subx-name
31462     3/imm32/rm32-is-first-output
31463     0/imm32/no-r32
31464     0/imm32/no-imm32
31465     0/imm32/no-imm8
31466     0/imm32/no-disp32
31467     0/imm32/no-xm32
31468     0/imm32/no-x32
31469     0x11/imm32/alloc-id:fake
31470     _Primitive-negate-mem/imm32/next
31471 _Primitive-negate-mem:  # (payload primitive)
31472     0x11/imm32/alloc-id:fake:payload
31473     # negate var1 => f7 3/subop/negate var1/rm32
31474     0x11/imm32/alloc-id:fake
31475     _string-negate/imm32/name
31476     0x11/imm32/alloc-id:fake
31477     Single-int-var-in-mem/imm32/inouts
31478     0/imm32/no-outputs
31479     0/imm32/no-outputs
31480     0x11/imm32/alloc-id:fake
31481     _string_f7_subop_negate/imm32/subx-name
31482     1/imm32/rm32-is-first-inout
31483     0/imm32/no-r32
31484     0/imm32/no-imm32
31485     0/imm32/no-imm8
31486     0/imm32/no-disp32
31487     0/imm32/no-xm32
31488     0/imm32/no-x32
31489     0x11/imm32/alloc-id:fake
31490     _Primitive-multiply-reg-by-reg/imm32/next
31491 # - multiply
31492 _Primitive-multiply-reg-by-reg:  # (payload primitive)
31493     0x11/imm32/alloc-id:fake:payload
31494     # var1/reg <- multiply var2 => 0f af/multiply var2/rm32 var1/r32
31495     0x11/imm32/alloc-id:fake
31496     _string-multiply/imm32/name
31497     0x11/imm32/alloc-id:fake
31498     Single-int-var-in-some-register/imm32/inouts
31499     0x11/imm32/alloc-id:fake
31500     Single-int-var-in-some-register/imm32/outputs
31501     0x11/imm32/alloc-id:fake
31502     _string_0f_af_multiply/imm32/subx-name
31503     1/imm32/rm32-is-first-inout
31504     3/imm32/r32-is-first-output
31505     0/imm32/no-imm32
31506     0/imm32/no-imm8
31507     0/imm32/no-disp32
31508     0/imm32/no-xm32
31509     0/imm32/no-x32
31510     0x11/imm32/alloc-id:fake
31511     _Primitive-multiply-reg-by-mem/imm32/next
31512 _Primitive-multiply-reg-by-mem:  # (payload primitive)
31513     0x11/imm32/alloc-id:fake:payload
31514     # var1/reg <- multiply var2 => 0f af/multiply var2/rm32 var1/r32
31515     0x11/imm32/alloc-id:fake
31516     _string-multiply/imm32/name
31517     0x11/imm32/alloc-id:fake
31518     Single-int-var-in-mem/imm32/inouts
31519     0x11/imm32/alloc-id:fake
31520     Single-int-var-in-some-register/imm32/outputs
31521     0x11/imm32/alloc-id:fake
31522     _string_0f_af_multiply/imm32/subx-name
31523     1/imm32/rm32-is-first-inout
31524     3/imm32/r32-is-first-output
31525     0/imm32/no-imm32
31526     0/imm32/no-imm8
31527     0/imm32/no-disp32
31528     0/imm32/no-xm32
31529     0/imm32/no-x32
31530     0x11/imm32/alloc-id:fake
31531     _Primitive-convert-mem-to-xreg/imm32/next
31532 # - convert int to floating point
31533 _Primitive-convert-mem-to-xreg:  # (payload primitive)
31534     0x11/imm32/alloc-id:fake:payload
31535     # var1/xreg <- convert var2 => f3 0f 2a/convert-to-float var2/rm32 var1/x32
31536     0x11/imm32/alloc-id:fake
31537     _string-convert/imm32/name
31538     0x11/imm32/alloc-id:fake
31539     Single-int-var-in-mem/imm32/inouts
31540     0x11/imm32/alloc-id:fake
31541     Single-float-var-in-some-register/imm32/outputs
31542     0x11/imm32/alloc-id:fake
31543     _string_f3_0f_2a_convert_to_float/imm32/subx-name
31544     1/imm32/rm32-is-first-inout
31545     0/imm32/no-r32
31546     0/imm32/no-imm32
31547     0/imm32/no-imm8
31548     0/imm32/no-disp32
31549     0/imm32/no-xm32
31550     3/imm32/x32-is-first-output
31551     0x11/imm32/alloc-id:fake
31552     _Primitive-convert-reg-to-xreg/imm32/next
31553 _Primitive-convert-reg-to-xreg:  # (payload primitive)
31554     0x11/imm32/alloc-id:fake:payload
31555     # var1/xreg <- convert var2/reg => f3 0f 2a/convert-to-float var2/rm32 var1/x32
31556     0x11/imm32/alloc-id:fake
31557     _string-convert/imm32/name
31558     0x11/imm32/alloc-id:fake
31559     Single-int-var-in-some-register/imm32/inouts
31560     0x11/imm32/alloc-id:fake
31561     Single-float-var-in-some-register/imm32/outputs
31562     0x11/imm32/alloc-id:fake
31563     _string_f3_0f_2a_convert_to_float/imm32/subx-name
31564     1/imm32/rm32-is-first-inout
31565     0/imm32/no-r32
31566     0/imm32/no-imm32
31567     0/imm32/no-imm8
31568     0/imm32/no-disp32
31569     0/imm32/no-xm32
31570     3/imm32/x32-is-first-output
31571     0x11/imm32/alloc-id:fake
31572     _Primitive-convert-xmem-to-reg/imm32/next
31573 # - convert floating point to int
31574 _Primitive-convert-xmem-to-reg:  # (payload primitive)
31575     0x11/imm32/alloc-id:fake:payload
31576     # var1/reg <- convert var2 => f3 0f 2d/convert-to-int var2/xm32 var1/r32
31577     0x11/imm32/alloc-id:fake
31578     _string-convert/imm32/name
31579     0x11/imm32/alloc-id:fake
31580     Single-float-var-in-mem/imm32/inouts
31581     0x11/imm32/alloc-id:fake
31582     Single-int-var-in-some-register/imm32/outputs
31583     0x11/imm32/alloc-id:fake
31584     _string_f3_0f_2d_convert_to_int/imm32/subx-name
31585     0/imm32/no-rm32
31586     3/imm32/r32-is-first-output
31587     0/imm32/no-imm32
31588     0/imm32/no-imm8
31589     0/imm32/no-disp32
31590     1/imm32/xm32-is-first-inout
31591     0/imm32/no-x32
31592     0x11/imm32/alloc-id:fake
31593     _Primitive-convert-xreg-to-reg/imm32/next
31594 _Primitive-convert-xreg-to-reg:  # (payload primitive)
31595     0x11/imm32/alloc-id:fake:payload
31596     # var1/reg <- convert var2/xreg => f3 0f 2d/convert-to-int var2/xm32 var1/r32
31597     0x11/imm32/alloc-id:fake
31598     _string-convert/imm32/name
31599     0x11/imm32/alloc-id:fake
31600     Single-float-var-in-some-register/imm32/inouts
31601     0x11/imm32/alloc-id:fake
31602     Single-int-var-in-some-register/imm32/outputs
31603     0x11/imm32/alloc-id:fake
31604     _string_f3_0f_2d_convert_to_int/imm32/subx-name
31605     0/imm32/no-rm32
31606     3/imm32/r32-is-first-output
31607     0/imm32/no-imm32
31608     0/imm32/no-imm8
31609     0/imm32/no-disp32
31610     1/imm32/xm32-is-first-inout
31611     0/imm32/no-x32
31612     0x11/imm32/alloc-id:fake
31613     _Primitive-truncate-xmem-to-reg/imm32/next
31614 _Primitive-truncate-xmem-to-reg:  # (payload primitive)
31615     0x11/imm32/alloc-id:fake:payload
31616     # var1/reg <- truncate var2 => f3 0f 2c/truncate-to-int var2/xm32 var1/r32
31617     0x11/imm32/alloc-id:fake
31618     _string-truncate/imm32/name
31619     0x11/imm32/alloc-id:fake
31620     Single-float-var-in-mem/imm32/inouts
31621     0x11/imm32/alloc-id:fake
31622     Single-int-var-in-some-register/imm32/outputs
31623     0x11/imm32/alloc-id:fake
31624     _string_f3_0f_2c_truncate_to_int/imm32/subx-name
31625     0/imm32/no-rm32
31626     3/imm32/r32-is-first-output
31627     0/imm32/no-imm32
31628     0/imm32/no-imm8
31629     0/imm32/no-disp32
31630     1/imm32/xm32-is-first-inout
31631     0/imm32/no-x32
31632     0x11/imm32/alloc-id:fake
31633     _Primitive-truncate-xreg-to-reg/imm32/next
31634 _Primitive-truncate-xreg-to-reg:  # (payload primitive)
31635     0x11/imm32/alloc-id:fake:payload
31636     # var1/reg <- truncate var2/xreg => f3 0f 2c/truncate-to-int var2/xm32 var1/r32
31637     0x11/imm32/alloc-id:fake
31638     _string-truncate/imm32/name
31639     0x11/imm32/alloc-id:fake
31640     Single-float-var-in-some-register/imm32/inouts
31641     0x11/imm32/alloc-id:fake
31642     Single-int-var-in-some-register/imm32/outputs
31643     0x11/imm32/alloc-id:fake
31644     _string_f3_0f_2c_truncate_to_int/imm32/subx-name
31645     0/imm32/no-rm32
31646     3/imm32/r32-is-first-output
31647     0/imm32/no-imm32
31648     0/imm32/no-imm8
31649     0/imm32/no-disp32
31650     1/imm32/xm32-is-first-inout
31651     0/imm32/no-x32
31652     0x11/imm32/alloc-id:fake
31653     _Primitive-reinterpret-xmem-as-reg/imm32/next
31654 # - reinterpret bytes (just for debugging)
31655 _Primitive-reinterpret-xmem-as-reg:  # (payload primitive)
31656     0x11/imm32/alloc-id:fake:payload
31657     # var1/reg <- reinterpret var2 => 8b/-> var2/xm32 var1/r32
31658     0x11/imm32/alloc-id:fake
31659     _string-reinterpret/imm32/name
31660     0x11/imm32/alloc-id:fake
31661     Single-float-var-in-mem/imm32/inouts
31662     0x11/imm32/alloc-id:fake
31663     Single-int-var-in-some-register/imm32/outputs
31664     0x11/imm32/alloc-id:fake
31665     _string_8b_->/imm32/subx-name
31666     0/imm32/no-rm32
31667     3/imm32/r32-is-first-output
31668     0/imm32/no-imm32
31669     0/imm32/no-imm8
31670     0/imm32/no-disp32
31671     1/imm32/xm32-is-first-inout
31672     0/imm32/no-x32
31673     0x11/imm32/alloc-id:fake
31674     _Primitive-reinterpret-mem-as-xreg/imm32/next
31675 _Primitive-reinterpret-mem-as-xreg:  # (payload primitive)
31676     0x11/imm32/alloc-id:fake:payload
31677     # var1/xreg <- reinterpret var2 => f3 0f 10/-> var2/rm32 var1/x32
31678     0x11/imm32/alloc-id:fake
31679     _string-reinterpret/imm32/name
31680     0x11/imm32/alloc-id:fake
31681     Single-int-var-in-mem/imm32/inouts
31682     0x11/imm32/alloc-id:fake
31683     Single-float-var-in-some-register/imm32/outputs
31684     0x11/imm32/alloc-id:fake
31685     _string_f3_0f_10_copy/imm32/subx-name
31686     1/imm32/rm32-is-first-inout
31687     0/imm32/no-r32
31688     0/imm32/no-imm32
31689     0/imm32/no-imm8
31690     0/imm32/no-disp32
31691     0/imm32/no-xm32
31692     3/imm32/x32-is-first-output
31693     0x11/imm32/alloc-id:fake
31694     _Primitive-copy-xreg-to-xreg/imm32/next
31695 # - floating-point copy
31696 _Primitive-copy-xreg-to-xreg:  # (payload primitive)
31697     0x11/imm32/alloc-id:fake:payload
31698     # var1/xreg <- copy var2/xreg => f3 0f 11/<- var1/xm32 var2/x32
31699     0x11/imm32/alloc-id:fake
31700     _string-copy/imm32/name
31701     0x11/imm32/alloc-id:fake
31702     Single-float-var-in-some-register/imm32/inouts
31703     0x11/imm32/alloc-id:fake
31704     Single-float-var-in-some-register/imm32/outputs
31705     0x11/imm32/alloc-id:fake
31706     _string_f3_0f_11_copy/imm32/subx-name
31707     0/imm32/no-rm32
31708     0/imm32/no-r32
31709     0/imm32/no-imm32
31710     0/imm32/no-imm8
31711     0/imm32/no-disp32
31712     3/imm32/xm32-is-first-output
31713     1/imm32/x32-is-first-inout
31714     0x11/imm32/alloc-id:fake
31715     _Primitive-copy-xreg-to-mem/imm32/next
31716 _Primitive-copy-xreg-to-mem:  # (payload primitive)
31717     0x11/imm32/alloc-id:fake:payload
31718     # copy-to var1 var2/xreg => f3 0f 11/<- var1 var2/x32
31719     0x11/imm32/alloc-id:fake
31720     _string-copy-to/imm32/name
31721     0x11/imm32/alloc-id:fake
31722     Two-args-float-stack-float-reg/imm32/inouts
31723     0/imm32/no-outputs
31724     0/imm32/no-outputs
31725     0x11/imm32/alloc-id:fake
31726     _string_f3_0f_11_copy/imm32/subx-name
31727     0/imm32/no-rm32
31728     0/imm32/no-r32
31729     0/imm32/no-imm32
31730     0/imm32/no-imm8
31731     0/imm32/no-disp32
31732     1/imm32/xm32-is-first-inout
31733     2/imm32/x32-is-second-inout
31734     0x11/imm32/alloc-id:fake
31735     _Primitive-copy-mem-to-xreg/imm32/next
31736 _Primitive-copy-mem-to-xreg:  # (payload primitive)
31737     0x11/imm32/alloc-id:fake:payload
31738     # var1/xreg <- copy var2 => f3 0f 10/-> var2/rm32 var1/x32
31739     0x11/imm32/alloc-id:fake
31740     _string-copy/imm32/name
31741     0x11/imm32/alloc-id:fake
31742     Single-float-var-in-mem/imm32/inouts
31743     0x11/imm32/alloc-id:fake
31744     Single-float-var-in-some-register/imm32/outputs
31745     0x11/imm32/alloc-id:fake
31746     _string_f3_0f_10_copy/imm32/subx-name
31747     0/imm32/no-rm32
31748     0/imm32/no-r32
31749     0/imm32/no-imm32
31750     0/imm32/no-imm8
31751     0/imm32/no-disp32
31752     1/imm32/xm32-is-first-inout
31753     3/imm32/x32-is-first-output
31754     0x11/imm32/alloc-id:fake
31755     _Primitive-address-of-xmem/imm32/next
31756 # - floating-point-address
31757 _Primitive-address-of-xmem:  # (payload primitive)
31758     0x11/imm32/alloc-id:fake:payload
31759     # var1/reg <- address var2 => 8d/copy-address var2/rm32 var1/r32
31760     0x11/imm32/alloc-id:fake
31761     _string-address/imm32/name
31762     0x11/imm32/alloc-id:fake
31763     Single-float-var-in-mem/imm32/inouts
31764     0x11/imm32/alloc-id:fake
31765     Single-addr-var-in-some-register/imm32/outputs
31766     0x11/imm32/alloc-id:fake
31767     _string_8d_copy_address/imm32/subx-name
31768     1/imm32/rm32-is-first-inout
31769     3/imm32/r32-is-first-output
31770     0/imm32/no-imm32
31771     0/imm32/no-imm8
31772     0/imm32/no-disp32
31773     0/imm32/no-xm32
31774     0/imm32/no-x32
31775     0x11/imm32/alloc-id:fake
31776     _Primitive-add-xreg-to-xreg/imm32/next
31777 # - floating-point add
31778 _Primitive-add-xreg-to-xreg:  # (payload primitive)
31779     0x11/imm32/alloc-id:fake:payload
31780     # var1/xreg <- add var2/xreg => f3 0f 58/add var1/xm32 var2/x32
31781     0x11/imm32/alloc-id:fake
31782     _string-add/imm32/name
31783     0x11/imm32/alloc-id:fake
31784     Single-float-var-in-some-register/imm32/inouts
31785     0x11/imm32/alloc-id:fake
31786     Single-float-var-in-some-register/imm32/outputs
31787     0x11/imm32/alloc-id:fake
31788     _string_f3_0f_58_add/imm32/subx-name
31789     0/imm32/no-rm32
31790     0/imm32/no-r32
31791     0/imm32/no-imm32
31792     0/imm32/no-imm8
31793     0/imm32/no-disp32
31794     1/imm32/xm32-is-first-inout
31795     3/imm32/x32-is-first-output
31796     0x11/imm32/alloc-id:fake
31797     _Primitive-add-mem-to-xreg/imm32/next
31798 _Primitive-add-mem-to-xreg:  # (payload primitive)
31799     0x11/imm32/alloc-id:fake:payload
31800     # var1/xreg <- add var2 => f3 0f 58/add var2/xm32 var1/x32
31801     0x11/imm32/alloc-id:fake
31802     _string-add/imm32/name
31803     0x11/imm32/alloc-id:fake
31804     Single-float-var-in-mem/imm32/inouts
31805     0x11/imm32/alloc-id:fake
31806     Single-float-var-in-some-register/imm32/outputs
31807     0x11/imm32/alloc-id:fake
31808     _string_f3_0f_58_add/imm32/subx-name
31809     0/imm32/no-rm32
31810     0/imm32/no-r32
31811     0/imm32/no-imm32
31812     0/imm32/no-imm8
31813     0/imm32/no-disp32
31814     1/imm32/xm32-is-first-inout
31815     3/imm32/x32-is-first-output
31816     0x11/imm32/alloc-id:fake
31817     _Primitive-subtract-xreg-from-xreg/imm32/next
31818 # - floating-point subtract
31819 _Primitive-subtract-xreg-from-xreg:  # (payload primitive)
31820     0x11/imm32/alloc-id:fake:payload
31821     # var1/xreg <- subtract var2/xreg => f3 0f 5c/subtract var1/xm32 var2/x32
31822     0x11/imm32/alloc-id:fake
31823     _string-subtract/imm32/name
31824     0x11/imm32/alloc-id:fake
31825     Single-float-var-in-some-register/imm32/inouts
31826     0x11/imm32/alloc-id:fake
31827     Single-float-var-in-some-register/imm32/outputs
31828     0x11/imm32/alloc-id:fake
31829     _string_f3_0f_5c_subtract/imm32/subx-name
31830     0/imm32/no-rm32
31831     0/imm32/no-r32
31832     0/imm32/no-imm32
31833     0/imm32/no-imm8
31834     0/imm32/no-disp32
31835     1/imm32/xm32-is-first-inout
31836     3/imm32/x32-is-first-output
31837     0x11/imm32/alloc-id:fake
31838     _Primitive-subtract-mem-from-xreg/imm32/next
31839 _Primitive-subtract-mem-from-xreg:  # (payload primitive)
31840     0x11/imm32/alloc-id:fake:payload
31841     # var1/xreg <- subtract var2 => f3 0f 5c/subtract var2/xm32 var1/x32
31842     0x11/imm32/alloc-id:fake
31843     _string-subtract/imm32/name
31844     0x11/imm32/alloc-id:fake
31845     Single-float-var-in-mem/imm32/inouts
31846     0x11/imm32/alloc-id:fake
31847     Single-float-var-in-some-register/imm32/outputs
31848     0x11/imm32/alloc-id:fake
31849     _string_f3_0f_5c_subtract/imm32/subx-name
31850     0/imm32/no-rm32
31851     0/imm32/no-r32
31852     0/imm32/no-imm32
31853     0/imm32/no-imm8
31854     0/imm32/no-disp32
31855     1/imm32/xm32-is-first-inout
31856     3/imm32/x32-is-first-output
31857     0x11/imm32/alloc-id:fake
31858     _Primitive-multiply-xreg-by-xreg/imm32/next
31859 # - floating-point multiply
31860 _Primitive-multiply-xreg-by-xreg:  # (payload primitive)
31861     0x11/imm32/alloc-id:fake:payload
31862     # var1/xreg <- multiply var2 => f3 0f 59/multiply var2/xm32 var1/x32
31863     0x11/imm32/alloc-id:fake
31864     _string-multiply/imm32/name
31865     0x11/imm32/alloc-id:fake
31866     Single-float-var-in-some-register/imm32/inouts
31867     0x11/imm32/alloc-id:fake
31868     Single-float-var-in-some-register/imm32/outputs
31869     0x11/imm32/alloc-id:fake
31870     _string_f3_0f_59_multiply/imm32/subx-name
31871     0/imm32/no-rm32
31872     0/imm32/no-r32
31873     0/imm32/no-imm32
31874     0/imm32/no-imm8
31875     0/imm32/no-disp32
31876     1/imm32/xm32-is-first-inout
31877     3/imm32/x32-is-first-output
31878     0x11/imm32/alloc-id:fake
31879     _Primitive-multiply-xreg-by-mem/imm32/next
31880 _Primitive-multiply-xreg-by-mem:  # (payload primitive)
31881     0x11/imm32/alloc-id:fake:payload
31882     # var1/xreg <- multiply var2 => 53 0f 59/multiply var2/xm32 var1/x32
31883     0x11/imm32/alloc-id:fake
31884     _string-multiply/imm32/name
31885     0x11/imm32/alloc-id:fake
31886     Single-float-var-in-mem/imm32/inouts
31887     0x11/imm32/alloc-id:fake
31888     Single-float-var-in-some-register/imm32/outputs
31889     0x11/imm32/alloc-id:fake
31890     _string_f3_0f_59_multiply/imm32/subx-name
31891     0/imm32/no-rm32
31892     0/imm32/no-r32
31893     0/imm32/no-imm32
31894     0/imm32/no-imm8
31895     0/imm32/no-disp32
31896     1/imm32/xm32-is-first-inout
31897     3/imm32/x32-is-first-output
31898     0x11/imm32/alloc-id:fake
31899     _Primitive-divide-xreg-by-xreg/imm32/next
31900 # - floating-point divide
31901 _Primitive-divide-xreg-by-xreg:  # (payload primitive)
31902     0x11/imm32/alloc-id:fake:payload
31903     # var1/xreg <- divide var2 => f3 0f 5e/divide var2/xm32 var1/x32
31904     0x11/imm32/alloc-id:fake
31905     _string-divide/imm32/name
31906     0x11/imm32/alloc-id:fake
31907     Single-float-var-in-some-register/imm32/inouts
31908     0x11/imm32/alloc-id:fake
31909     Single-float-var-in-some-register/imm32/outputs
31910     0x11/imm32/alloc-id:fake
31911     _string_f3_0f_5e_divide/imm32/subx-name
31912     0/imm32/no-rm32
31913     0/imm32/no-r32
31914     0/imm32/no-imm32
31915     0/imm32/no-imm8
31916     0/imm32/no-disp32
31917     1/imm32/xm32-is-first-inout
31918     3/imm32/x32-is-first-output
31919     0x11/imm32/alloc-id:fake
31920     _Primitive-divide-xreg-by-mem/imm32/next
31921 _Primitive-divide-xreg-by-mem:  # (payload primitive)
31922     0x11/imm32/alloc-id:fake:payload
31923     # var1/xreg <- divide var2 => f3 0f 5e/divide var2/xm32 var1/x32
31924     0x11/imm32/alloc-id:fake
31925     _string-divide/imm32/name
31926     0x11/imm32/alloc-id:fake
31927     Single-float-var-in-mem/imm32/inouts
31928     0x11/imm32/alloc-id:fake
31929     Single-float-var-in-some-register/imm32/outputs
31930     0x11/imm32/alloc-id:fake
31931     _string_f3_0f_5e_divide/imm32/subx-name
31932     0/imm32/no-rm32
31933     0/imm32/no-r32
31934     0/imm32/no-imm32
31935     0/imm32/no-imm8
31936     0/imm32/no-disp32
31937     1/imm32/xm32-is-first-inout
31938     3/imm32/x32-is-first-output
31939     0x11/imm32/alloc-id:fake
31940     _Primitive-max-xreg-with-xreg/imm32/next
31941 # - floating-point maximum
31942 _Primitive-max-xreg-with-xreg:  # (payload primitive)
31943     0x11/imm32/alloc-id:fake:payload
31944     # var1/xreg <- max var2 => f3 0f 5f/max var2/xm32 var1/x32
31945     0x11/imm32/alloc-id:fake
31946     _string-max/imm32/name
31947     0x11/imm32/alloc-id:fake
31948     Single-float-var-in-some-register/imm32/inouts
31949     0x11/imm32/alloc-id:fake
31950     Single-float-var-in-some-register/imm32/outputs
31951     0x11/imm32/alloc-id:fake
31952     _string_f3_0f_5f_max/imm32/subx-name
31953     0/imm32/no-rm32
31954     0/imm32/no-r32
31955     0/imm32/no-imm32
31956     0/imm32/no-imm8
31957     0/imm32/no-disp32
31958     1/imm32/xm32-is-first-inout
31959     3/imm32/x32-is-first-output
31960     0x11/imm32/alloc-id:fake
31961     _Primitive-max-xreg-with-mem/imm32/next
31962 _Primitive-max-xreg-with-mem:  # (payload primitive)
31963     0x11/imm32/alloc-id:fake:payload
31964     # var1/xreg <- divide var2 => f3 0f 5f/max var2/xm32 var1/x32
31965     0x11/imm32/alloc-id:fake
31966     _string-max/imm32/name
31967     0x11/imm32/alloc-id:fake
31968     Single-float-var-in-mem/imm32/inouts
31969     0x11/imm32/alloc-id:fake
31970     Single-float-var-in-some-register/imm32/outputs
31971     0x11/imm32/alloc-id:fake
31972     _string_f3_0f_5f_max/imm32/subx-name
31973     0/imm32/no-rm32
31974     0/imm32/no-r32
31975     0/imm32/no-imm32
31976     0/imm32/no-imm8
31977     0/imm32/no-disp32
31978     1/imm32/xm32-is-first-inout
31979     3/imm32/x32-is-first-output
31980     0x11/imm32/alloc-id:fake
31981     _Primitive-min-xreg-with-xreg/imm32/next
31982 # - floating-point minimum
31983 _Primitive-min-xreg-with-xreg:  # (payload primitive)
31984     0x11/imm32/alloc-id:fake:payload
31985     # var1/xreg <- divide var2 => f3 0f 5d/min var2/xm32 var1/x32
31986     0x11/imm32/alloc-id:fake
31987     _string-min/imm32/name
31988     0x11/imm32/alloc-id:fake
31989     Single-float-var-in-some-register/imm32/inouts
31990     0x11/imm32/alloc-id:fake
31991     Single-float-var-in-some-register/imm32/outputs
31992     0x11/imm32/alloc-id:fake
31993     _string_f3_0f_5d_min/imm32/subx-name
31994     0/imm32/no-rm32
31995     0/imm32/no-r32
31996     0/imm32/no-imm32
31997     0/imm32/no-imm8
31998     0/imm32/no-disp32
31999     1/imm32/xm32-is-first-inout
32000     3/imm32/x32-is-first-output
32001     0x11/imm32/alloc-id:fake
32002     _Primitive-min-xreg-with-mem/imm32/next
32003 _Primitive-min-xreg-with-mem:  # (payload primitive)
32004     0x11/imm32/alloc-id:fake:payload
32005     # var1/xreg <- divide var2 => f3 0f 5d/min var2/xm32 var1/x32
32006     0x11/imm32/alloc-id:fake
32007     _string-min/imm32/name
32008     0x11/imm32/alloc-id:fake
32009     Single-float-var-in-mem/imm32/inouts
32010     0x11/imm32/alloc-id:fake
32011     Single-float-var-in-some-register/imm32/outputs
32012     0x11/imm32/alloc-id:fake
32013     _string_f3_0f_5d_min/imm32/subx-name
32014     0/imm32/no-rm32
32015     0/imm32/no-r32
32016     0/imm32/no-imm32
32017     0/imm32/no-imm8
32018     0/imm32/no-disp32
32019     1/imm32/xm32-is-first-inout
32020     3/imm32/x32-is-first-output
32021     0x11/imm32/alloc-id:fake
32022     _Primitive-reciprocal-xreg-to-xreg/imm32/next
32023 # - floating-point reciprocal
32024 _Primitive-reciprocal-xreg-to-xreg:  # (payload primitive)
32025     0x11/imm32/alloc-id:fake:payload
32026     # var1/xreg <- reciprocal var2 => f3 0f 53/reciprocal var2/xm32 var1/x32
32027     0x11/imm32/alloc-id:fake
32028     _string-reciprocal/imm32/name
32029     0x11/imm32/alloc-id:fake
32030     Single-float-var-in-some-register/imm32/inouts
32031     0x11/imm32/alloc-id:fake
32032     Single-float-var-in-some-register/imm32/outputs
32033     0x11/imm32/alloc-id:fake
32034     _string_f3_0f_53_reciprocal/imm32/subx-name
32035     0/imm32/no-rm32
32036     0/imm32/no-r32
32037     0/imm32/no-imm32
32038     0/imm32/no-imm8
32039     0/imm32/no-disp32
32040     1/imm32/xm32-is-first-inout
32041     3/imm32/x32-is-first-output
32042     0x11/imm32/alloc-id:fake
32043     _Primitive-reciprocal-mem-to-xreg/imm32/next
32044 _Primitive-reciprocal-mem-to-xreg:  # (payload primitive)
32045     0x11/imm32/alloc-id:fake:payload
32046     # var1/xreg <- divide var2 => f3 0f 53/reciprocal var2/xm32 var1/x32
32047     0x11/imm32/alloc-id:fake
32048     _string-reciprocal/imm32/name
32049     0x11/imm32/alloc-id:fake
32050     Single-float-var-in-mem/imm32/inouts
32051     0x11/imm32/alloc-id:fake
32052     Single-float-var-in-some-register/imm32/outputs
32053     0x11/imm32/alloc-id:fake
32054     _string_f3_0f_53_reciprocal/imm32/subx-name
32055     0/imm32/no-rm32
32056     0/imm32/no-r32
32057     0/imm32/no-imm32
32058     0/imm32/no-imm8
32059     0/imm32/no-disp32
32060     1/imm32/xm32-is-first-inout
32061     3/imm32/x32-is-first-output
32062     0x11/imm32/alloc-id:fake
32063     _Primitive-square-root-xreg-to-xreg/imm32/next
32064 # - floating-point square root
32065 _Primitive-square-root-xreg-to-xreg:  # (payload primitive)
32066     0x11/imm32/alloc-id:fake:payload
32067     # var1/xreg <- square-root var2 => f3 0f 51/square-root var2/xm32 var1/x32
32068     0x11/imm32/alloc-id:fake
32069     _string-square-root/imm32/name
32070     0x11/imm32/alloc-id:fake
32071     Single-float-var-in-some-register/imm32/inouts
32072     0x11/imm32/alloc-id:fake
32073     Single-float-var-in-some-register/imm32/outputs
32074     0x11/imm32/alloc-id:fake
32075     _string_f3_0f_51_square_root/imm32/subx-name
32076     0/imm32/no-rm32
32077     0/imm32/no-r32
32078     0/imm32/no-imm32
32079     0/imm32/no-imm8
32080     0/imm32/no-disp32
32081     1/imm32/xm32-is-first-inout
32082     3/imm32/x32-is-first-output
32083     0x11/imm32/alloc-id:fake
32084     _Primitive-square-root-mem-to-xreg/imm32/next
32085 _Primitive-square-root-mem-to-xreg:  # (payload primitive)
32086     0x11/imm32/alloc-id:fake:payload
32087     # var1/xreg <- divide var2 => f3 0f 51/square-root var2/xm32 var1/x32
32088     0x11/imm32/alloc-id:fake
32089     _string-square-root/imm32/name
32090     0x11/imm32/alloc-id:fake
32091     Single-float-var-in-mem/imm32/inouts
32092     0x11/imm32/alloc-id:fake
32093     Single-float-var-in-some-register/imm32/outputs
32094     0x11/imm32/alloc-id:fake
32095     _string_f3_0f_51_square_root/imm32/subx-name
32096     0/imm32/no-rm32
32097     0/imm32/no-r32
32098     0/imm32/no-imm32
32099     0/imm32/no-imm8
32100     0/imm32/no-disp32
32101     1/imm32/xm32-is-first-inout
32102     3/imm32/x32-is-first-output
32103     0x11/imm32/alloc-id:fake
32104     _Primitive-inverse-square-root-xreg-to-xreg/imm32/next
32105 # - floating-point inverse square root 1/sqrt(x)
32106 _Primitive-inverse-square-root-xreg-to-xreg:  # (payload primitive)
32107     0x11/imm32/alloc-id:fake:payload
32108     # var1/xreg <- reciprocal var2 => f3 0f 52/inverse-square-root var2/xm32 var1/x32
32109     0x11/imm32/alloc-id:fake
32110     _string-inverse-square-root/imm32/name
32111     0x11/imm32/alloc-id:fake
32112     Single-float-var-in-some-register/imm32/inouts
32113     0x11/imm32/alloc-id:fake
32114     Single-float-var-in-some-register/imm32/outputs
32115     0x11/imm32/alloc-id:fake
32116     _string_f3_0f_52_inverse_square_root/imm32/subx-name
32117     0/imm32/no-rm32
32118     0/imm32/no-r32
32119     0/imm32/no-imm32
32120     0/imm32/no-imm8
32121     0/imm32/no-disp32
32122     1/imm32/xm32-is-first-inout
32123     3/imm32/x32-is-first-output
32124     0x11/imm32/alloc-id:fake
32125     _Primitive-inverse-square-root-mem-to-xreg/imm32/next
32126 _Primitive-inverse-square-root-mem-to-xreg:  # (payload primitive)
32127     0x11/imm32/alloc-id:fake:payload
32128     # var1/xreg <- divide var2 => f3 0f 52/inverse-square-root var2/xm32 var1/x32
32129     0x11/imm32/alloc-id:fake
32130     _string-inverse-square-root/imm32/name
32131     0x11/imm32/alloc-id:fake
32132     Single-float-var-in-mem/imm32/inouts
32133     0x11/imm32/alloc-id:fake
32134     Single-float-var-in-some-register/imm32/outputs
32135     0x11/imm32/alloc-id:fake
32136     _string_f3_0f_52_inverse_square_root/imm32/subx-name
32137     0/imm32/no-rm32
32138     0/imm32/no-r32
32139     0/imm32/no-imm32
32140     0/imm32/no-imm8
32141     0/imm32/no-disp32
32142     1/imm32/xm32-is-first-inout
32143     3/imm32/x32-is-first-output
32144     0x11/imm32/alloc-id:fake
32145     _Primitive-compare-xreg-with-xreg/imm32/next
32146 # - floating-point compare
32147 _Primitive-compare-xreg-with-xreg:  # (payload primitive)
32148     0x11/imm32/alloc-id:fake:payload
32149     # compare var1/reg1 var2/reg2 => 0f 2f/compare var2/x32 var1/xm32
32150     0x11/imm32/alloc-id:fake
32151     _string-compare/imm32/name
32152     0x11/imm32/alloc-id:fake
32153     Two-float-args-in-regs/imm32/inouts
32154     0/imm32/no-outputs
32155     0/imm32/no-outputs
32156     0x11/imm32/alloc-id:fake
32157     _string_0f_2f_compare/imm32/subx-name
32158     0/imm32/no-rm32
32159     0/imm32/no-r32
32160     0/imm32/no-imm32
32161     0/imm32/no-imm8
32162     0/imm32/no-disp32
32163     1/imm32/xm32-is-first-inout
32164     2/imm32/x32-is-second-inout
32165     0x11/imm32/alloc-id:fake
32166     _Primitive-compare-xreg-with-mem/imm32/next
32167 _Primitive-compare-xreg-with-mem:  # (payload primitive)
32168     0x11/imm32/alloc-id:fake:payload
32169     # compare var1/xreg var2 => 0f 2f/compare var1/x32 var2/xm32
32170     0x11/imm32/alloc-id:fake
32171     _string-compare/imm32/name
32172     0x11/imm32/alloc-id:fake
32173     Two-args-float-reg-float-stack/imm32/inouts
32174     0/imm32/no-outputs
32175     0/imm32/no-outputs
32176     0x11/imm32/alloc-id:fake
32177     _string_0f_2f_compare/imm32/subx-name
32178     0/imm32/no-rm32
32179     0/imm32/no-r32
32180     0/imm32/no-imm32
32181     0/imm32/no-imm8
32182     0/imm32/no-disp32
32183     2/imm32/xm32-is-second-inout
32184     1/imm32/x32-is-first-inout
32185     0x11/imm32/alloc-id:fake
32186     _Primitive-break-if-addr</imm32/next
32187 # - branches
32188 _Primitive-break-if-addr<:  # (payload primitive)
32189     0x11/imm32/alloc-id:fake:payload
32190     0x11/imm32/alloc-id:fake
32191     _string-break-if-addr</imm32/name
32192     0/imm32/no-inouts
32193     0/imm32/no-inouts
32194     0/imm32/no-outputs
32195     0/imm32/no-outputs
32196     0x11/imm32/alloc-id:fake
32197     _string_0f_82_jump_break/imm32/subx-name
32198     0/imm32/no-rm32
32199     0/imm32/no-r32
32200     0/imm32/no-imm32
32201     0/imm32/no-imm8
32202     0/imm32/no-disp32
32203     0/imm32/no-xm32
32204     0/imm32/no-x32
32205     0x11/imm32/alloc-id:fake
32206     _Primitive-break-if-addr>=/imm32/next
32207 _Primitive-break-if-addr>=:  # (payload primitive)
32208     0x11/imm32/alloc-id:fake:payload
32209     0x11/imm32/alloc-id:fake
32210     _string-break-if-addr>=/imm32/name
32211     0/imm32/no-inouts
32212     0/imm32/no-inouts
32213     0/imm32/no-outputs
32214     0/imm32/no-outputs
32215     0x11/imm32/alloc-id:fake
32216     _string_0f_83_jump_break/imm32/subx-name
32217     0/imm32/no-rm32
32218     0/imm32/no-r32
32219     0/imm32/no-imm32
32220     0/imm32/no-imm8
32221     0/imm32/no-disp32
32222     0/imm32/no-xm32
32223     0/imm32/no-x32
32224     0x11/imm32/alloc-id:fake
32225     _Primitive-break-if-=/imm32/next
32226 _Primitive-break-if-=:  # (payload primitive)
32227     0x11/imm32/alloc-id:fake:payload
32228     0x11/imm32/alloc-id:fake
32229     _string-break-if-=/imm32/name
32230     0/imm32/no-inouts
32231     0/imm32/no-inouts
32232     0/imm32/no-outputs
32233     0/imm32/no-outputs
32234     0x11/imm32/alloc-id:fake
32235     _string_0f_84_jump_break/imm32/subx-name
32236     0/imm32/no-rm32
32237     0/imm32/no-r32
32238     0/imm32/no-imm32
32239     0/imm32/no-imm8
32240     0/imm32/no-disp32
32241     0/imm32/no-xm32
32242     0/imm32/no-x32
32243     0x11/imm32/alloc-id:fake
32244     _Primitive-break-if-!=/imm32/next
32245 _Primitive-break-if-!=:  # (payload primitive)
32246     0x11/imm32/alloc-id:fake:payload
32247     0x11/imm32/alloc-id:fake
32248     _string-break-if-!=/imm32/name
32249     0/imm32/no-inouts
32250     0/imm32/no-inouts
32251     0/imm32/no-outputs
32252     0/imm32/no-outputs
32253     0x11/imm32/alloc-id:fake
32254     _string_0f_85_jump_break/imm32/subx-name
32255     0/imm32/no-rm32
32256     0/imm32/no-r32
32257     0/imm32/no-imm32
32258     0/imm32/no-imm8
32259     0/imm32/no-disp32
32260     0/imm32/no-xm32
32261     0/imm32/no-x32
32262     0x11/imm32/alloc-id:fake
32263     _Primitive-break-if-addr<=/imm32/next
32264 _Primitive-break-if-addr<=:  # (payload primitive)
32265     0x11/imm32/alloc-id:fake:payload
32266     0x11/imm32/alloc-id:fake
32267     _string-break-if-addr<=/imm32/name
32268     0/imm32/no-inouts
32269     0/imm32/no-inouts
32270     0/imm32/no-outputs
32271     0/imm32/no-outputs
32272     0x11/imm32/alloc-id:fake
32273     _string_0f_86_jump_break/imm32/subx-name
32274     0/imm32/no-rm32
32275     0/imm32/no-r32
32276     0/imm32/no-imm32
32277     0/imm32/no-imm8
32278     0/imm32/no-disp32
32279     0/imm32/no-xm32
32280     0/imm32/no-x32
32281     0x11/imm32/alloc-id:fake
32282     _Primitive-break-if-addr>/imm32/next
32283 _Primitive-break-if-addr>:  # (payload primitive)
32284     0x11/imm32/alloc-id:fake:payload
32285     0x11/imm32/alloc-id:fake
32286     _string-break-if-addr>/imm32/name
32287     0/imm32/no-inouts
32288     0/imm32/no-inouts
32289     0/imm32/no-outputs
32290     0/imm32/no-outputs
32291     0x11/imm32/alloc-id:fake
32292     _string_0f_87_jump_break/imm32/subx-name
32293     0/imm32/no-rm32
32294     0/imm32/no-r32
32295     0/imm32/no-imm32
32296     0/imm32/no-imm8
32297     0/imm32/no-disp32
32298     0/imm32/no-xm32
32299     0/imm32/no-x32
32300     0x11/imm32/alloc-id:fake
32301     _Primitive-break-if-</imm32/next
32302 _Primitive-break-if-<:  # (payload primitive)
32303     0x11/imm32/alloc-id:fake:payload
32304     0x11/imm32/alloc-id:fake
32305     _string-break-if-</imm32/name
32306     0/imm32/no-inouts
32307     0/imm32/no-inouts
32308     0/imm32/no-outputs
32309     0/imm32/no-outputs
32310     0x11/imm32/alloc-id:fake
32311     _string_0f_8c_jump_break/imm32/subx-name
32312     0/imm32/no-rm32
32313     0/imm32/no-r32
32314     0/imm32/no-imm32
32315     0/imm32/no-imm8
32316     0/imm32/no-disp32
32317     0/imm32/no-xm32
32318     0/imm32/no-x32
32319     0x11/imm32/alloc-id:fake
32320     _Primitive-break-if->=/imm32/next
32321 _Primitive-break-if->=:  # (payload primitive)
32322     0x11/imm32/alloc-id:fake:payload
32323     0x11/imm32/alloc-id:fake
32324     _string-break-if->=/imm32/name
32325     0/imm32/no-inouts
32326     0/imm32/no-inouts
32327     0/imm32/no-outputs
32328     0/imm32/no-outputs
32329     0x11/imm32/alloc-id:fake
32330     _string_0f_8d_jump_break/imm32/subx-name
32331     0/imm32/no-rm32
32332     0/imm32/no-r32
32333     0/imm32/no-imm32
32334     0/imm32/no-imm8
32335     0/imm32/no-disp32
32336     0/imm32/no-xm32
32337     0/imm32/no-x32
32338     0x11/imm32/alloc-id:fake
32339     _Primitive-break-if-<=/imm32/next
32340 _Primitive-break-if-<=:  # (payload primitive)
32341     0x11/imm32/alloc-id:fake:payload
32342     0x11/imm32/alloc-id:fake
32343     _string-break-if-<=/imm32/name
32344     0/imm32/no-inouts
32345     0/imm32/no-inouts
32346     0/imm32/no-outputs
32347     0/imm32/no-outputs
32348     0x11/imm32/alloc-id:fake
32349     _string_0f_8e_jump_break/imm32/subx-name
32350     0/imm32/no-rm32
32351     0/imm32/no-r32
32352     0/imm32/no-imm32
32353     0/imm32/no-imm8
32354     0/imm32/no-disp32
32355     0/imm32/no-xm32
32356     0/imm32/no-x32
32357     0x11/imm32/alloc-id:fake
32358     _Primitive-break-if->/imm32/next
32359 _Primitive-break-if->:  # (payload primitive)
32360     0x11/imm32/alloc-id:fake:payload
32361     0x11/imm32/alloc-id:fake
32362     _string-break-if->/imm32/name
32363     0/imm32/no-inouts
32364     0/imm32/no-inouts
32365     0/imm32/no-outputs
32366     0/imm32/no-outputs
32367     0x11/imm32/alloc-id:fake
32368     _string_0f_8f_jump_break/imm32/subx-name
32369     0/imm32/no-rm32
32370     0/imm32/no-r32
32371     0/imm32/no-imm32
32372     0/imm32/no-imm8
32373     0/imm32/no-disp32
32374     0/imm32/no-xm32
32375     0/imm32/no-x32
32376     0x11/imm32/alloc-id:fake
32377     _Primitive-break/imm32/next
32378 _Primitive-break:  # (payload primitive)
32379     0x11/imm32/alloc-id:fake:payload
32380     0x11/imm32/alloc-id:fake
32381     _string-break/imm32/name
32382     0/imm32/no-inouts
32383     0/imm32/no-inouts
32384     0/imm32/no-outputs
32385     0/imm32/no-outputs
32386     0x11/imm32/alloc-id:fake
32387     _string_e9_jump_break/imm32/subx-name
32388     0/imm32/no-rm32
32389     0/imm32/no-r32
32390     0/imm32/no-imm32
32391     0/imm32/no-imm8
32392     0/imm32/no-disp32
32393     0/imm32/no-xm32
32394     0/imm32/no-x32
32395     0x11/imm32/alloc-id:fake
32396     _Primitive-loop-if-addr</imm32/next
32397 _Primitive-loop-if-addr<:  # (payload primitive)
32398     0x11/imm32/alloc-id:fake:payload
32399     0x11/imm32/alloc-id:fake
32400     _string-loop-if-addr</imm32/name
32401     0/imm32/no-inouts
32402     0/imm32/no-inouts
32403     0/imm32/no-outputs
32404     0/imm32/no-outputs
32405     0x11/imm32/alloc-id:fake
32406     _string_0f_82_jump_loop/imm32/subx-name
32407     0/imm32/no-rm32
32408     0/imm32/no-r32
32409     0/imm32/no-imm32
32410     0/imm32/no-imm8
32411     0/imm32/no-disp32
32412     0/imm32/no-xm32
32413     0/imm32/no-x32
32414     0x11/imm32/alloc-id:fake
32415     _Primitive-loop-if-addr>=/imm32/next
32416 _Primitive-loop-if-addr>=:  # (payload primitive)
32417     0x11/imm32/alloc-id:fake:payload
32418     0x11/imm32/alloc-id:fake
32419     _string-loop-if-addr>=/imm32/name
32420     0/imm32/no-inouts
32421     0/imm32/no-inouts
32422     0/imm32/no-outputs
32423     0/imm32/no-outputs
32424     0x11/imm32/alloc-id:fake
32425     _string_0f_83_jump_loop/imm32/subx-name
32426     0/imm32/no-rm32
32427     0/imm32/no-r32
32428     0/imm32/no-imm32
32429     0/imm32/no-imm8
32430     0/imm32/no-disp32
32431     0/imm32/no-xm32
32432     0/imm32/no-x32
32433     0x11/imm32/alloc-id:fake
32434     _Primitive-loop-if-=/imm32/next
32435 _Primitive-loop-if-=:  # (payload primitive)
32436     0x11/imm32/alloc-id:fake:payload
32437     0x11/imm32/alloc-id:fake
32438     _string-loop-if-=/imm32/name
32439     0/imm32/no-inouts
32440     0/imm32/no-inouts
32441     0/imm32/no-outputs
32442     0/imm32/no-outputs
32443     0x11/imm32/alloc-id:fake
32444     _string_0f_84_jump_loop/imm32/subx-name
32445     0/imm32/no-rm32
32446     0/imm32/no-r32
32447     0/imm32/no-imm32
32448     0/imm32/no-imm8
32449     0/imm32/no-disp32
32450     0/imm32/no-xm32
32451     0/imm32/no-x32
32452     0x11/imm32/alloc-id:fake
32453     _Primitive-loop-if-!=/imm32/next
32454 _Primitive-loop-if-!=:  # (payload primitive)
32455     0x11/imm32/alloc-id:fake:payload
32456     0x11/imm32/alloc-id:fake
32457     _string-loop-if-!=/imm32/name
32458     0/imm32/no-inouts
32459     0/imm32/no-inouts
32460     0/imm32/no-outputs
32461     0/imm32/no-outputs
32462     0x11/imm32/alloc-id:fake
32463     _string_0f_85_jump_loop/imm32/subx-name
32464     0/imm32/no-rm32
32465     0/imm32/no-r32
32466     0/imm32/no-imm32
32467     0/imm32/no-imm8
32468     0/imm32/no-disp32
32469     0/imm32/no-xm32
32470     0/imm32/no-x32
32471     0x11/imm32/alloc-id:fake
32472     _Primitive-loop-if-addr<=/imm32/next
32473 _Primitive-loop-if-addr<=:  # (payload primitive)
32474     0x11/imm32/alloc-id:fake:payload
32475     0x11/imm32/alloc-id:fake
32476     _string-loop-if-addr<=/imm32/name
32477     0/imm32/no-inouts
32478     0/imm32/no-inouts
32479     0/imm32/no-outputs
32480     0/imm32/no-outputs
32481     0x11/imm32/alloc-id:fake
32482     _string_0f_86_jump_loop/imm32/subx-name
32483     0/imm32/no-rm32
32484     0/imm32/no-r32
32485     0/imm32/no-imm32
32486     0/imm32/no-imm8
32487     0/imm32/no-disp32
32488     0/imm32/no-xm32
32489     0/imm32/no-x32
32490     0x11/imm32/alloc-id:fake
32491     _Primitive-loop-if-addr>/imm32/next
32492 _Primitive-loop-if-addr>:  # (payload primitive)
32493     0x11/imm32/alloc-id:fake:payload
32494     0x11/imm32/alloc-id:fake
32495     _string-loop-if-addr>/imm32/name
32496     0/imm32/no-inouts
32497     0/imm32/no-inouts
32498     0/imm32/no-outputs
32499     0/imm32/no-outputs
32500     0x11/imm32/alloc-id:fake
32501     _string_0f_87_jump_loop/imm32/subx-name
32502     0/imm32/no-rm32
32503     0/imm32/no-r32
32504     0/imm32/no-imm32
32505     0/imm32/no-imm8
32506     0/imm32/no-disp32
32507     0/imm32/no-xm32
32508     0/imm32/no-x32
32509     0x11/imm32/alloc-id:fake
32510     _Primitive-loop-if-</imm32/next
32511 _Primitive-loop-if-<:  # (payload primitive)
32512     0x11/imm32/alloc-id:fake:payload
32513     0x11/imm32/alloc-id:fake
32514     _string-loop-if-</imm32/name
32515     0/imm32/no-inouts
32516     0/imm32/no-inouts
32517     0/imm32/no-outputs
32518     0/imm32/no-outputs
32519     0x11/imm32/alloc-id:fake
32520     _string_0f_8c_jump_loop/imm32/subx-name
32521     0/imm32/no-rm32
32522     0/imm32/no-r32
32523     0/imm32/no-imm32
32524     0/imm32/no-imm8
32525     0/imm32/no-disp32
32526     0/imm32/no-xm32
32527     0/imm32/no-x32
32528     0x11/imm32/alloc-id:fake
32529     _Primitive-loop-if->=/imm32/next
32530 _Primitive-loop-if->=:  # (payload primitive)
32531     0x11/imm32/alloc-id:fake:payload
32532     0x11/imm32/alloc-id:fake
32533     _string-loop-if->=/imm32/name
32534     0/imm32/no-inouts
32535     0/imm32/no-inouts
32536     0/imm32/no-outputs
32537     0/imm32/no-outputs
32538     0x11/imm32/alloc-id:fake
32539     _string_0f_8d_jump_loop/imm32/subx-name
32540     0/imm32/no-rm32
32541     0/imm32/no-r32
32542     0/imm32/no-imm32
32543     0/imm32/no-imm8
32544     0/imm32/no-disp32
32545     0/imm32/no-xm32
32546     0/imm32/no-x32
32547     0x11/imm32/alloc-id:fake
32548     _Primitive-loop-if-<=/imm32/next
32549 _Primitive-loop-if-<=:  # (payload primitive)
32550     0x11/imm32/alloc-id:fake:payload
32551     0x11/imm32/alloc-id:fake
32552     _string-loop-if-<=/imm32/name
32553     0/imm32/no-inouts
32554     0/imm32/no-inouts
32555     0/imm32/no-outputs
32556     0/imm32/no-outputs
32557     0x11/imm32/alloc-id:fake
32558     _string_0f_8e_jump_loop/imm32/subx-name
32559     0/imm32/no-rm32
32560     0/imm32/no-r32
32561     0/imm32/no-imm32
32562     0/imm32/no-imm8
32563     0/imm32/no-disp32
32564     0/imm32/no-xm32
32565     0/imm32/no-x32
32566     0x11/imm32/alloc-id:fake
32567     _Primitive-loop-if->/imm32/next
32568 _Primitive-loop-if->:  # (payload primitive)
32569     0x11/imm32/alloc-id:fake:payload
32570     0x11/imm32/alloc-id:fake
32571     _string-loop-if->/imm32/name
32572     0/imm32/no-inouts
32573     0/imm32/no-inouts
32574     0/imm32/no-outputs
32575     0/imm32/no-outputs
32576     0x11/imm32/alloc-id:fake
32577     _string_0f_8f_jump_loop/imm32/subx-name
32578     0/imm32/no-rm32
32579     0/imm32/no-r32
32580     0/imm32/no-imm32
32581     0/imm32/no-imm8
32582     0/imm32/no-disp32
32583     0/imm32/no-xm32
32584     0/imm32/no-x32
32585     0x11/imm32/alloc-id:fake
32586     _Primitive-loop/imm32/next  # we probably don't need an unconditional break
32587 _Primitive-loop:  # (payload primitive)
32588     0x11/imm32/alloc-id:fake:payload
32589     0x11/imm32/alloc-id:fake
32590     _string-loop/imm32/name
32591     0/imm32/no-inouts
32592     0/imm32/no-inouts
32593     0/imm32/no-outputs
32594     0/imm32/no-outputs
32595     0x11/imm32/alloc-id:fake
32596     _string_e9_jump_loop/imm32/subx-name
32597     0/imm32/no-rm32
32598     0/imm32/no-r32
32599     0/imm32/no-imm32
32600     0/imm32/no-imm8
32601     0/imm32/no-disp32
32602     0/imm32/no-xm32
32603     0/imm32/no-x32
32604     0x11/imm32/alloc-id:fake
32605     _Primitive-break-if-addr<-named/imm32/next
32606 # - branches to named blocks
32607 _Primitive-break-if-addr<-named:  # (payload primitive)
32608     0x11/imm32/alloc-id:fake:payload
32609     0x11/imm32/alloc-id:fake
32610     _string-break-if-addr</imm32/name
32611     0x11/imm32/alloc-id:fake
32612     Single-lit-var/imm32/inouts
32613     0/imm32/no-outputs
32614     0/imm32/no-outputs
32615     0x11/imm32/alloc-id:fake
32616     _string_0f_82_jump_label/imm32/subx-name
32617     0/imm32/no-rm32
32618     0/imm32/no-r32
32619     0/imm32/no-imm32
32620     0/imm32/no-imm8
32621     1/imm32/disp32-is-first-inout
32622     0/imm32/no-xm32
32623     0/imm32/no-x32
32624     0x11/imm32/alloc-id:fake
32625     _Primitive-break-if-addr>=-named/imm32/next
32626 _Primitive-break-if-addr>=-named:  # (payload primitive)
32627     0x11/imm32/alloc-id:fake:payload
32628     0x11/imm32/alloc-id:fake
32629     _string-break-if-addr>=/imm32/name
32630     0x11/imm32/alloc-id:fake
32631     Single-lit-var/imm32/inouts
32632     0/imm32/no-outputs
32633     0/imm32/no-outputs
32634     0x11/imm32/alloc-id:fake
32635     _string_0f_83_jump_label/imm32/subx-name
32636     0/imm32/no-rm32
32637     0/imm32/no-r32
32638     0/imm32/no-imm32
32639     0/imm32/no-imm8
32640     1/imm32/disp32-is-first-inout
32641     0/imm32/no-xm32
32642     0/imm32/no-x32
32643     0x11/imm32/alloc-id:fake
32644     _Primitive-break-if-=-named/imm32/next
32645 _Primitive-break-if-=-named:  # (payload primitive)
32646     0x11/imm32/alloc-id:fake:payload
32647     0x11/imm32/alloc-id:fake
32648     _string-break-if-=/imm32/name
32649     0x11/imm32/alloc-id:fake
32650     Single-lit-var/imm32/inouts
32651     0/imm32/no-outputs
32652     0/imm32/no-outputs
32653     0x11/imm32/alloc-id:fake
32654     _string_0f_84_jump_label/imm32/subx-name
32655     0/imm32/no-rm32
32656     0/imm32/no-r32
32657     0/imm32/no-imm32
32658     0/imm32/no-imm8
32659     1/imm32/disp32-is-first-inout
32660     0/imm32/no-xm32
32661     0/imm32/no-x32
32662     0x11/imm32/alloc-id:fake
32663     _Primitive-break-if-!=-named/imm32/next
32664 _Primitive-break-if-!=-named:  # (payload primitive)
32665     0x11/imm32/alloc-id:fake:payload
32666     0x11/imm32/alloc-id:fake
32667     _string-break-if-!=/imm32/name
32668     0x11/imm32/alloc-id:fake
32669     Single-lit-var/imm32/inouts
32670     0/imm32/no-outputs
32671     0/imm32/no-outputs
32672     0x11/imm32/alloc-id:fake
32673     _string_0f_85_jump_label/imm32/subx-name
32674     0/imm32/no-rm32
32675     0/imm32/no-r32
32676     0/imm32/no-imm32
32677     0/imm32/no-imm8
32678     1/imm32/disp32-is-first-inout
32679     0/imm32/no-xm32
32680     0/imm32/no-x32
32681     0x11/imm32/alloc-id:fake
32682     _Primitive-break-if-addr<=-named/imm32/next
32683 _Primitive-break-if-addr<=-named:  # (payload primitive)
32684     0x11/imm32/alloc-id:fake:payload
32685     0x11/imm32/alloc-id:fake
32686     _string-break-if-addr<=/imm32/name
32687     0x11/imm32/alloc-id:fake
32688     Single-lit-var/imm32/inouts
32689     0/imm32/no-outputs
32690     0/imm32/no-outputs
32691     0x11/imm32/alloc-id:fake
32692     _string_0f_86_jump_label/imm32/subx-name
32693     0/imm32/no-rm32
32694     0/imm32/no-r32
32695     0/imm32/no-imm32
32696     0/imm32/no-imm8
32697     1/imm32/disp32-is-first-inout
32698     0/imm32/no-xm32
32699     0/imm32/no-x32
32700     0x11/imm32/alloc-id:fake
32701     _Primitive-break-if-addr>-named/imm32/next
32702 _Primitive-break-if-addr>-named:  # (payload primitive)
32703     0x11/imm32/alloc-id:fake:payload
32704     0x11/imm32/alloc-id:fake
32705     _string-break-if-addr>/imm32/name
32706     0x11/imm32/alloc-id:fake
32707     Single-lit-var/imm32/inouts
32708     0/imm32/no-outputs
32709     0/imm32/no-outputs
32710     0x11/imm32/alloc-id:fake
32711     _string_0f_87_jump_label/imm32/subx-name
32712     0/imm32/no-rm32
32713     0/imm32/no-r32
32714     0/imm32/no-imm32
32715     0/imm32/no-imm8
32716     1/imm32/disp32-is-first-inout
32717     0/imm32/no-xm32
32718     0/imm32/no-x32
32719     0x11/imm32/alloc-id:fake
32720     _Primitive-break-if-<-named/imm32/next
32721 _Primitive-break-if-<-named:  # (payload primitive)
32722     0x11/imm32/alloc-id:fake:payload
32723     0x11/imm32/alloc-id:fake
32724     _string-break-if-</imm32/name
32725     0x11/imm32/alloc-id:fake
32726     Single-lit-var/imm32/inouts
32727     0/imm32/no-outputs
32728     0/imm32/no-outputs
32729     0x11/imm32/alloc-id:fake
32730     _string_0f_8c_jump_label/imm32/subx-name
32731     0/imm32/no-rm32
32732     0/imm32/no-r32
32733     0/imm32/no-imm32
32734     0/imm32/no-imm8
32735     1/imm32/disp32-is-first-inout
32736     0/imm32/no-xm32
32737     0/imm32/no-x32
32738     0x11/imm32/alloc-id:fake
32739     _Primitive-break-if->=-named/imm32/next
32740 _Primitive-break-if->=-named:  # (payload primitive)
32741     0x11/imm32/alloc-id:fake:payload
32742     0x11/imm32/alloc-id:fake
32743     _string-break-if->=/imm32/name
32744     0x11/imm32/alloc-id:fake
32745     Single-lit-var/imm32/inouts
32746     0/imm32/no-outputs
32747     0/imm32/no-outputs
32748     0x11/imm32/alloc-id:fake
32749     _string_0f_8d_jump_label/imm32/subx-name
32750     0/imm32/no-rm32
32751     0/imm32/no-r32
32752     0/imm32/no-imm32
32753     0/imm32/no-imm8
32754     1/imm32/disp32-is-first-inout
32755     0/imm32/no-xm32
32756     0/imm32/no-x32
32757     0x11/imm32/alloc-id:fake
32758     _Primitive-break-if-<=-named/imm32/next
32759 _Primitive-break-if-<=-named:  # (payload primitive)
32760     0x11/imm32/alloc-id:fake:payload
32761     0x11/imm32/alloc-id:fake
32762     _string-break-if-<=/imm32/name
32763     0x11/imm32/alloc-id:fake
32764     Single-lit-var/imm32/inouts
32765     0/imm32/no-outputs
32766     0/imm32/no-outputs
32767     0x11/imm32/alloc-id:fake
32768     _string_0f_8e_jump_label/imm32/subx-name
32769     0/imm32/no-rm32
32770     0/imm32/no-r32
32771     0/imm32/no-imm32
32772     0/imm32/no-imm8
32773     1/imm32/disp32-is-first-inout
32774     0/imm32/no-xm32
32775     0/imm32/no-x32
32776     0x11/imm32/alloc-id:fake
32777     _Primitive-break-if->-named/imm32/next
32778 _Primitive-break-if->-named:  # (payload primitive)
32779     0x11/imm32/alloc-id:fake:payload
32780     0x11/imm32/alloc-id:fake
32781     _string-break-if->/imm32/name
32782     0x11/imm32/alloc-id:fake
32783     Single-lit-var/imm32/inouts
32784     0/imm32/no-outputs
32785     0/imm32/no-outputs
32786     0x11/imm32/alloc-id:fake
32787     _string_0f_8f_jump_label/imm32/subx-name
32788     0/imm32/no-rm32
32789     0/imm32/no-r32
32790     0/imm32/no-imm32
32791     0/imm32/no-imm8
32792     1/imm32/disp32-is-first-inout
32793     0/imm32/no-xm32
32794     0/imm32/no-x32
32795     0x11/imm32/alloc-id:fake
32796     _Primitive-break-named/imm32/next
32797 _Primitive-break-named:  # (payload primitive)
32798     0x11/imm32/alloc-id:fake:payload
32799     0x11/imm32/alloc-id:fake
32800     _string-break/imm32/name
32801     0x11/imm32/alloc-id:fake
32802     Single-lit-var/imm32/inouts
32803     0/imm32/no-outputs
32804     0/imm32/no-outputs
32805     0x11/imm32/alloc-id:fake
32806     _string_e9_jump_label/imm32/subx-name
32807     0/imm32/no-rm32
32808     0/imm32/no-r32
32809     0/imm32/no-imm32
32810     0/imm32/no-imm8
32811     1/imm32/disp32-is-first-inout
32812     0/imm32/no-xm32
32813     0/imm32/no-x32
32814     0x11/imm32/alloc-id:fake
32815     _Primitive-loop-if-addr<-named/imm32/next
32816 _Primitive-loop-if-addr<-named:  # (payload primitive)
32817     0x11/imm32/alloc-id:fake:payload
32818     0x11/imm32/alloc-id:fake
32819     _string-loop-if-addr</imm32/name
32820     0x11/imm32/alloc-id:fake
32821     Single-lit-var/imm32/inouts
32822     0/imm32/no-outputs
32823     0/imm32/no-outputs
32824     0x11/imm32/alloc-id:fake
32825     _string_0f_82_jump_label/imm32/subx-name
32826     0/imm32/no-rm32
32827     0/imm32/no-r32
32828     0/imm32/no-imm32
32829     0/imm32/no-imm8
32830     1/imm32/disp32-is-first-inout
32831     0/imm32/no-xm32
32832     0/imm32/no-x32
32833     0x11/imm32/alloc-id:fake
32834     _Primitive-loop-if-addr>=-named/imm32/next
32835 _Primitive-loop-if-addr>=-named:  # (payload primitive)
32836     0x11/imm32/alloc-id:fake:payload
32837     0x11/imm32/alloc-id:fake
32838     _string-loop-if-addr>=/imm32/name
32839     0x11/imm32/alloc-id:fake
32840     Single-lit-var/imm32/inouts
32841     0/imm32/no-outputs
32842     0/imm32/no-outputs
32843     0x11/imm32/alloc-id:fake
32844     _string_0f_83_jump_label/imm32/subx-name
32845     0/imm32/no-rm32
32846     0/imm32/no-r32
32847     0/imm32/no-imm32
32848     0/imm32/no-imm8
32849     1/imm32/disp32-is-first-inout
32850     0/imm32/no-xm32
32851     0/imm32/no-x32
32852     0x11/imm32/alloc-id:fake
32853     _Primitive-loop-if-=-named/imm32/next
32854 _Primitive-loop-if-=-named:  # (payload primitive)
32855     0x11/imm32/alloc-id:fake:payload
32856     0x11/imm32/alloc-id:fake
32857     _string-loop-if-=/imm32/name
32858     0x11/imm32/alloc-id:fake
32859     Single-lit-var/imm32/inouts
32860     0/imm32/no-outputs
32861     0/imm32/no-outputs
32862     0x11/imm32/alloc-id:fake
32863     _string_0f_84_jump_label/imm32/subx-name
32864     0/imm32/no-rm32
32865     0/imm32/no-r32
32866     0/imm32/no-imm32
32867     0/imm32/no-imm8
32868     1/imm32/disp32-is-first-inout
32869     0/imm32/no-xm32
32870     0/imm32/no-x32
32871     0x11/imm32/alloc-id:fake
32872     _Primitive-loop-if-!=-named/imm32/next
32873 _Primitive-loop-if-!=-named:  # (payload primitive)
32874     0x11/imm32/alloc-id:fake:payload
32875     0x11/imm32/alloc-id:fake
32876     _string-loop-if-!=/imm32/name
32877     0x11/imm32/alloc-id:fake
32878     Single-lit-var/imm32/inouts
32879     0/imm32/no-outputs
32880     0/imm32/no-outputs
32881     0x11/imm32/alloc-id:fake
32882     _string_0f_85_jump_label/imm32/subx-name
32883     0/imm32/no-rm32
32884     0/imm32/no-r32
32885     0/imm32/no-imm32
32886     0/imm32/no-imm8
32887     1/imm32/disp32-is-first-inout
32888     0/imm32/no-xm32
32889     0/imm32/no-x32
32890     0x11/imm32/alloc-id:fake
32891     _Primitive-loop-if-addr<=-named/imm32/next
32892 _Primitive-loop-if-addr<=-named:  # (payload primitive)
32893     0x11/imm32/alloc-id:fake:payload
32894     0x11/imm32/alloc-id:fake
32895     _string-loop-if-addr<=/imm32/name
32896     0x11/imm32/alloc-id:fake
32897     Single-lit-var/imm32/inouts
32898     0/imm32/no-outputs
32899     0/imm32/no-outputs
32900     0x11/imm32/alloc-id:fake
32901     _string_0f_86_jump_label/imm32/subx-name
32902     0/imm32/no-rm32
32903     0/imm32/no-r32
32904     0/imm32/no-imm32
32905     0/imm32/no-imm8
32906     1/imm32/disp32-is-first-inout
32907     0/imm32/no-xm32
32908     0/imm32/no-x32
32909     0x11/imm32/alloc-id:fake
32910     _Primitive-loop-if-addr>-named/imm32/next
32911 _Primitive-loop-if-addr>-named:  # (payload primitive)
32912     0x11/imm32/alloc-id:fake:payload
32913     0x11/imm32/alloc-id:fake
32914     _string-loop-if-addr>/imm32/name
32915     0x11/imm32/alloc-id:fake
32916     Single-lit-var/imm32/inouts
32917     0/imm32/no-outputs
32918     0/imm32/no-outputs
32919     0x11/imm32/alloc-id:fake
32920     _string_0f_87_jump_label/imm32/subx-name
32921     0/imm32/no-rm32
32922     0/imm32/no-r32
32923     0/imm32/no-imm32
32924     0/imm32/no-imm8
32925     1/imm32/disp32-is-first-inout
32926     0/imm32/no-xm32
32927     0/imm32/no-x32
32928     0x11/imm32/alloc-id:fake
32929     _Primitive-loop-if-<-named/imm32/next
32930 _Primitive-loop-if-<-named:  # (payload primitive)
32931     0x11/imm32/alloc-id:fake:payload
32932     0x11/imm32/alloc-id:fake
32933     _string-loop-if-</imm32/name
32934     0x11/imm32/alloc-id:fake
32935     Single-lit-var/imm32/inouts
32936     0/imm32/no-outputs
32937     0/imm32/no-outputs
32938     0x11/imm32/alloc-id:fake
32939     _string_0f_8c_jump_label/imm32/subx-name
32940     0/imm32/no-rm32
32941     0/imm32/no-r32
32942     0/imm32/no-imm32
32943     0/imm32/no-imm8
32944     1/imm32/disp32-is-first-inout
32945     0/imm32/no-xm32
32946     0/imm32/no-x32
32947     0x11/imm32/alloc-id:fake
32948     _Primitive-loop-if->=-named/imm32/next
32949 _Primitive-loop-if->=-named:  # (payload primitive)
32950     0x11/imm32/alloc-id:fake:payload
32951     0x11/imm32/alloc-id:fake
32952     _string-loop-if->=/imm32/name
32953     0x11/imm32/alloc-id:fake
32954     Single-lit-var/imm32/inouts
32955     0/imm32/no-outputs
32956     0/imm32/no-outputs
32957     0x11/imm32/alloc-id:fake
32958     _string_0f_8d_jump_label/imm32/subx-name
32959     0/imm32/no-rm32
32960     0/imm32/no-r32
32961     0/imm32/no-imm32
32962     0/imm32/no-imm8
32963     1/imm32/disp32-is-first-inout
32964     0/imm32/no-xm32
32965     0/imm32/no-x32
32966     0x11/imm32/alloc-id:fake
32967     _Primitive-loop-if-<=-named/imm32/next
32968 _Primitive-loop-if-<=-named:  # (payload primitive)
32969     0x11/imm32/alloc-id:fake:payload
32970     0x11/imm32/alloc-id:fake
32971     _string-loop-if-<=/imm32/name
32972     0x11/imm32/alloc-id:fake
32973     Single-lit-var/imm32/inouts
32974     0/imm32/no-outputs
32975     0/imm32/no-outputs
32976     0x11/imm32/alloc-id:fake
32977     _string_0f_8e_jump_label/imm32/subx-name
32978     0/imm32/no-rm32
32979     0/imm32/no-r32
32980     0/imm32/no-imm32
32981     0/imm32/no-imm8
32982     1/imm32/disp32-is-first-inout
32983     0/imm32/no-xm32
32984     0/imm32/no-x32
32985     0x11/imm32/alloc-id:fake
32986     _Primitive-loop-if->-named/imm32/next
32987 _Primitive-loop-if->-named:  # (payload primitive)
32988     0x11/imm32/alloc-id:fake:payload
32989     0x11/imm32/alloc-id:fake
32990     _string-loop-if->/imm32/name
32991     0x11/imm32/alloc-id:fake
32992     Single-lit-var/imm32/inouts
32993     0/imm32/no-outputs
32994     0/imm32/no-outputs
32995     0x11/imm32/alloc-id:fake
32996     _string_0f_8f_jump_label/imm32/subx-name
32997     0/imm32/no-rm32
32998     0/imm32/no-r32
32999     0/imm32/no-imm32
33000     0/imm32/no-imm8
33001     1/imm32/disp32-is-first-inout
33002     0/imm32/no-xm32
33003     0/imm32/no-x32
33004     0x11/imm32/alloc-id:fake
33005     _Primitive-loop-named/imm32/next  # we probably don't need an unconditional break
33006 _Primitive-loop-named:  # (payload primitive)
33007     0x11/imm32/alloc-id:fake:payload
33008     0x11/imm32/alloc-id:fake
33009     _string-loop/imm32/name
33010     0x11/imm32/alloc-id:fake
33011     Single-lit-var/imm32/inouts
33012     0/imm32/no-outputs
33013     0/imm32/no-outputs
33014     0x11/imm32/alloc-id:fake
33015     _string_e9_jump_label/imm32/subx-name
33016     0/imm32/no-rm32
33017     0/imm32/no-r32
33018     0/imm32/no-imm32
33019     0/imm32/no-imm8
33020     1/imm32/disp32-is-first-inout
33021     0/imm32/no-xm32
33022     0/imm32/no-x32
33023     0x11/imm32/alloc-id:fake
33024     _Primitive-break-if-float</imm32/next
33025 # - branches based on floating-point comparisons
33026 _Primitive-break-if-float<:  # (payload primitive)
33027     0x11/imm32/alloc-id:fake:payload
33028     0x11/imm32/alloc-id:fake
33029     _string-break-if-float</imm32/name
33030     0/imm32/no-inouts
33031     0/imm32/no-inouts
33032     0/imm32/no-outputs
33033     0/imm32/no-outputs
33034     0x11/imm32/alloc-id:fake
33035     _string_0f_82_jump_break/imm32/subx-name
33036     0/imm32/no-rm32
33037     0/imm32/no-r32
33038     0/imm32/no-imm32
33039     0/imm32/no-imm8
33040     0/imm32/no-disp32
33041     0/imm32/no-xm32
33042     0/imm32/no-x32
33043     0x11/imm32/alloc-id:fake
33044     _Primitive-break-if-float>=/imm32/next
33045 _Primitive-break-if-float>=:  # (payload primitive)
33046     0x11/imm32/alloc-id:fake:payload
33047     0x11/imm32/alloc-id:fake
33048     _string-break-if-float>=/imm32/name
33049     0/imm32/no-inouts
33050     0/imm32/no-inouts
33051     0/imm32/no-outputs
33052     0/imm32/no-outputs
33053     0x11/imm32/alloc-id:fake
33054     _string_0f_83_jump_break/imm32/subx-name
33055     0/imm32/no-rm32
33056     0/imm32/no-r32
33057     0/imm32/no-imm32
33058     0/imm32/no-imm8
33059     0/imm32/no-disp32
33060     0/imm32/no-xm32
33061     0/imm32/no-x32
33062     0x11/imm32/alloc-id:fake
33063     _Primitive-break-if-float<=/imm32/next
33064 _Primitive-break-if-float<=:  # (payload primitive)
33065     0x11/imm32/alloc-id:fake:payload
33066     0x11/imm32/alloc-id:fake
33067     _string-break-if-float<=/imm32/name
33068     0/imm32/no-inouts
33069     0/imm32/no-inouts
33070     0/imm32/no-outputs
33071     0/imm32/no-outputs
33072     0x11/imm32/alloc-id:fake
33073     _string_0f_86_jump_break/imm32/subx-name
33074     0/imm32/no-rm32
33075     0/imm32/no-r32
33076     0/imm32/no-imm32
33077     0/imm32/no-imm8
33078     0/imm32/no-disp32
33079     0/imm32/no-xm32
33080     0/imm32/no-x32
33081     0x11/imm32/alloc-id:fake
33082     _Primitive-break-if-float>/imm32/next
33083 _Primitive-break-if-float>:  # (payload primitive)
33084     0x11/imm32/alloc-id:fake:payload
33085     0x11/imm32/alloc-id:fake
33086     _string-break-if-float>/imm32/name
33087     0/imm32/no-inouts
33088     0/imm32/no-inouts
33089     0/imm32/no-outputs
33090     0/imm32/no-outputs
33091     0x11/imm32/alloc-id:fake
33092     _string_0f_87_jump_break/imm32/subx-name
33093     0/imm32/no-rm32
33094     0/imm32/no-r32
33095     0/imm32/no-imm32
33096     0/imm32/no-imm8
33097     0/imm32/no-disp32
33098     0/imm32/no-xm32
33099     0/imm32/no-x32
33100     0x11/imm32/alloc-id:fake
33101     _Primitive-loop-if-float</imm32/next
33102 _Primitive-loop-if-float<:  # (payload primitive)
33103     0x11/imm32/alloc-id:fake:payload
33104     0x11/imm32/alloc-id:fake
33105     _string-loop-if-float</imm32/name
33106     0/imm32/no-inouts
33107     0/imm32/no-inouts
33108     0/imm32/no-outputs
33109     0/imm32/no-outputs
33110     0x11/imm32/alloc-id:fake
33111     _string_0f_82_jump_loop/imm32/subx-name
33112     0/imm32/no-rm32
33113     0/imm32/no-r32
33114     0/imm32/no-imm32
33115     0/imm32/no-imm8
33116     0/imm32/no-disp32
33117     0/imm32/no-xm32
33118     0/imm32/no-x32
33119     0x11/imm32/alloc-id:fake
33120     _Primitive-loop-if-float>=/imm32/next
33121 _Primitive-loop-if-float>=:  # (payload primitive)
33122     0x11/imm32/alloc-id:fake:payload
33123     0x11/imm32/alloc-id:fake
33124     _string-loop-if-float>=/imm32/name
33125     0/imm32/no-inouts
33126     0/imm32/no-inouts
33127     0/imm32/no-outputs
33128     0/imm32/no-outputs
33129     0x11/imm32/alloc-id:fake
33130     _string_0f_83_jump_loop/imm32/subx-name
33131     0/imm32/no-rm32
33132     0/imm32/no-r32
33133     0/imm32/no-imm32
33134     0/imm32/no-imm8
33135     0/imm32/no-disp32
33136     0/imm32/no-xm32
33137     0/imm32/no-x32
33138     0x11/imm32/alloc-id:fake
33139     _Primitive-loop-if-float<=/imm32/next
33140 _Primitive-loop-if-float<=:  # (payload primitive)
33141     0x11/imm32/alloc-id:fake:payload
33142     0x11/imm32/alloc-id:fake
33143     _string-loop-if-float<=/imm32/name
33144     0/imm32/no-inouts
33145     0/imm32/no-inouts
33146     0/imm32/no-outputs
33147     0/imm32/no-outputs
33148     0x11/imm32/alloc-id:fake
33149     _string_0f_86_jump_loop/imm32/subx-name
33150     0/imm32/no-rm32
33151     0/imm32/no-r32
33152     0/imm32/no-imm32
33153     0/imm32/no-imm8
33154     0/imm32/no-disp32
33155     0/imm32/no-xm32
33156     0/imm32/no-x32
33157     0x11/imm32/alloc-id:fake
33158     _Primitive-loop-if-float>/imm32/next
33159 _Primitive-loop-if-float>:  # (payload primitive)
33160     0x11/imm32/alloc-id:fake:payload
33161     0x11/imm32/alloc-id:fake
33162     _string-loop-if-float>/imm32/name
33163     0/imm32/no-inouts
33164     0/imm32/no-inouts
33165     0/imm32/no-outputs
33166     0/imm32/no-outputs
33167     0x11/imm32/alloc-id:fake
33168     _string_0f_87_jump_loop/imm32/subx-name
33169     0/imm32/no-rm32
33170     0/imm32/no-r32
33171     0/imm32/no-imm32
33172     0/imm32/no-imm8
33173     0/imm32/no-disp32
33174     0/imm32/no-xm32
33175     0/imm32/no-x32
33176     0x11/imm32/alloc-id:fake
33177     _Primitive-break-if-float<-named/imm32/next
33178 _Primitive-break-if-float<-named:  # (payload primitive)
33179     0x11/imm32/alloc-id:fake:payload
33180     0x11/imm32/alloc-id:fake
33181     _string-break-if-float</imm32/name
33182     0x11/imm32/alloc-id:fake
33183     Single-lit-var/imm32/inouts
33184     0/imm32/no-outputs
33185     0/imm32/no-outputs
33186     0x11/imm32/alloc-id:fake
33187     _string_0f_82_jump_label/imm32/subx-name
33188     0/imm32/no-rm32
33189     0/imm32/no-r32
33190     0/imm32/no-imm32
33191     0/imm32/no-imm8
33192     1/imm32/disp32-is-first-inout
33193     0/imm32/no-xm32
33194     0/imm32/no-x32
33195     0x11/imm32/alloc-id:fake
33196     _Primitive-break-if-float>=-named/imm32/next
33197 _Primitive-break-if-float>=-named:  # (payload primitive)
33198     0x11/imm32/alloc-id:fake:payload
33199     0x11/imm32/alloc-id:fake
33200     _string-break-if-float>=/imm32/name
33201     0x11/imm32/alloc-id:fake
33202     Single-lit-var/imm32/inouts
33203     0/imm32/no-outputs
33204     0/imm32/no-outputs
33205     0x11/imm32/alloc-id:fake
33206     _string_0f_83_jump_label/imm32/subx-name
33207     0/imm32/no-rm32
33208     0/imm32/no-r32
33209     0/imm32/no-imm32
33210     0/imm32/no-imm8
33211     1/imm32/disp32-is-first-inout
33212     0/imm32/no-xm32
33213     0/imm32/no-x32
33214     0x11/imm32/alloc-id:fake
33215     _Primitive-break-if-float<=-named/imm32/next
33216 _Primitive-break-if-float<=-named:  # (payload primitive)
33217     0x11/imm32/alloc-id:fake:payload
33218     0x11/imm32/alloc-id:fake
33219     _string-break-if-float<=/imm32/name
33220     0x11/imm32/alloc-id:fake
33221     Single-lit-var/imm32/inouts
33222     0/imm32/no-outputs
33223     0/imm32/no-outputs
33224     0x11/imm32/alloc-id:fake
33225     _string_0f_86_jump_label/imm32/subx-name
33226     0/imm32/no-rm32
33227     0/imm32/no-r32
33228     0/imm32/no-imm32
33229     0/imm32/no-imm8
33230     1/imm32/disp32-is-first-inout
33231     0/imm32/no-xm32
33232     0/imm32/no-x32
33233     0x11/imm32/alloc-id:fake
33234     _Primitive-break-if-float>-named/imm32/next
33235 _Primitive-break-if-float>-named:  # (payload primitive)
33236     0x11/imm32/alloc-id:fake:payload
33237     0x11/imm32/alloc-id:fake
33238     _string-break-if-float>/imm32/name
33239     0x11/imm32/alloc-id:fake
33240     Single-lit-var/imm32/inouts
33241     0/imm32/no-outputs
33242     0/imm32/no-outputs
33243     0x11/imm32/alloc-id:fake
33244     _string_0f_87_jump_label/imm32/subx-name
33245     0/imm32/no-rm32
33246     0/imm32/no-r32
33247     0/imm32/no-imm32
33248     0/imm32/no-imm8
33249     1/imm32/disp32-is-first-inout
33250     0/imm32/no-xm32
33251     0/imm32/no-x32
33252     0x11/imm32/alloc-id:fake
33253     _Primitive-loop-if-float<-named/imm32/next
33254 _Primitive-loop-if-float<-named:  # (payload primitive)
33255     0x11/imm32/alloc-id:fake:payload
33256     0x11/imm32/alloc-id:fake
33257     _string-loop-if-float</imm32/name
33258     0x11/imm32/alloc-id:fake
33259     Single-lit-var/imm32/inouts
33260     0/imm32/no-outputs
33261     0/imm32/no-outputs
33262     0x11/imm32/alloc-id:fake
33263     _string_0f_82_jump_label/imm32/subx-name
33264     0/imm32/no-rm32
33265     0/imm32/no-r32
33266     0/imm32/no-imm32
33267     0/imm32/no-imm8
33268     1/imm32/disp32-is-first-inout
33269     0/imm32/no-xm32
33270     0/imm32/no-x32
33271     0x11/imm32/alloc-id:fake
33272     _Primitive-loop-if-float>=-named/imm32/next
33273 _Primitive-loop-if-float>=-named:  # (payload primitive)
33274     0x11/imm32/alloc-id:fake:payload
33275     0x11/imm32/alloc-id:fake
33276     _string-loop-if-float>=/imm32/name
33277     0x11/imm32/alloc-id:fake
33278     Single-lit-var/imm32/inouts
33279     0/imm32/no-outputs
33280     0/imm32/no-outputs
33281     0x11/imm32/alloc-id:fake
33282     _string_0f_83_jump_label/imm32/subx-name
33283     0/imm32/no-rm32
33284     0/imm32/no-r32
33285     0/imm32/no-imm32
33286     0/imm32/no-imm8
33287     1/imm32/disp32-is-first-inout
33288     0/imm32/no-xm32
33289     0/imm32/no-x32
33290     0x11/imm32/alloc-id:fake
33291     _Primitive-loop-if-float<=-named/imm32/next
33292 _Primitive-loop-if-float<=-named:  # (payload primitive)
33293     0x11/imm32/alloc-id:fake:payload
33294     0x11/imm32/alloc-id:fake
33295     _string-loop-if-float<=/imm32/name
33296     0x11/imm32/alloc-id:fake
33297     Single-lit-var/imm32/inouts
33298     0/imm32/no-outputs
33299     0/imm32/no-outputs
33300     0x11/imm32/alloc-id:fake
33301     _string_0f_86_jump_label/imm32/subx-name
33302     0/imm32/no-rm32
33303     0/imm32/no-r32
33304     0/imm32/no-imm32
33305     0/imm32/no-imm8
33306     1/imm32/disp32-is-first-inout
33307     0/imm32/no-xm32
33308     0/imm32/no-x32
33309     0x11/imm32/alloc-id:fake
33310     _Primitive-loop-if-float>-named/imm32/next
33311 _Primitive-loop-if-float>-named:  # (payload primitive)
33312     0x11/imm32/alloc-id:fake:payload
33313     0x11/imm32/alloc-id:fake
33314     _string-loop-if-float>/imm32/name
33315     0x11/imm32/alloc-id:fake
33316     Single-lit-var/imm32/inouts
33317     0/imm32/no-outputs
33318     0/imm32/no-outputs
33319     0x11/imm32/alloc-id:fake
33320     _string_0f_87_jump_label/imm32/subx-name
33321     0/imm32/no-rm32
33322     0/imm32/no-r32
33323     0/imm32/no-imm32
33324     0/imm32/no-imm8
33325     1/imm32/disp32-is-first-inout
33326     0/imm32/no-xm32
33327     0/imm32/no-x32
33328     0/imm32/next
33329     0/imm32/next
33330 
33331 # string literals for Mu instructions
33332 _string-add:  # (payload array byte)
33333     0x11/imm32/alloc-id:fake:payload
33334     # "add"
33335     0x3/imm32/size
33336     0x61/a 0x64/d 0x64/d
33337 _string-address:  # (payload array byte)
33338     0x11/imm32/alloc-id:fake:payload
33339     # "address"
33340     0x7/imm32/size
33341     0x61/a 0x64/d 0x64/d 0x72/r 0x65/e 0x73/s 0x73/s
33342 _string-add-to:  # (payload array byte)
33343     0x11/imm32/alloc-id:fake:payload
33344     # "add-to"
33345     0x6/imm32/size
33346     0x61/a 0x64/d 0x64/d 0x2d/dash 0x74/t 0x6f/o
33347 _string-and:  # (payload array byte)
33348     0x11/imm32/alloc-id:fake:payload
33349     # "and"
33350     0x3/imm32/size
33351     0x61/a 0x6e/n 0x64/d
33352 _string-and-with:  # (payload array byte)
33353     0x11/imm32/alloc-id:fake:payload
33354     # "and-with"
33355     0x8/imm32/size
33356     0x61/a 0x6e/n 0x64/d 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
33357 _string-break:  # (payload array byte)
33358     0x11/imm32/alloc-id:fake:payload
33359     # "break"
33360     0x5/imm32/size
33361     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k
33362 _string-break-if-<:  # (payload array byte)
33363     0x11/imm32/alloc-id:fake:payload
33364     # "break-if-<"
33365     0xa/imm32/size
33366     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/<
33367 _string-break-if-<=:  # (payload array byte)
33368     0x11/imm32/alloc-id:fake:payload
33369     # "break-if-<="
33370     0xb/imm32/size
33371     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< 0x3d/=
33372 _string-break-if-=:  # (payload array byte)
33373     0x11/imm32/alloc-id:fake:payload
33374     # "break-if-="
33375     0xa/imm32/size
33376     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3d/=
33377 _string-break-if->:  # (payload array byte)
33378     0x11/imm32/alloc-id:fake:payload
33379     # "break-if->"
33380     0xa/imm32/size
33381     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/>
33382 _string-break-if->=:  # (payload array byte)
33383     0x11/imm32/alloc-id:fake:payload
33384     # "break-if->="
33385     0xb/imm32/size
33386     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> 0x3d/=
33387 _string-break-if-!=:  # (payload array byte)
33388     0x11/imm32/alloc-id:fake:payload
33389     # "break-if-!="
33390     0xb/imm32/size
33391     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x21/! 0x3d/=
33392 _string-break-if-addr<:  # (payload array byte)
33393     0x11/imm32/alloc-id:fake:payload
33394     # "break-if-addr<"
33395     0xe/imm32/size
33396     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/<
33397 _string-break-if-addr<=:  # (payload array byte)
33398     0x11/imm32/alloc-id:fake:payload
33399     # "break-if-addr<="
33400     0xf/imm32/size
33401     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/=
33402 _string-break-if-addr>:  # (payload array byte)
33403     0x11/imm32/alloc-id:fake:payload
33404     # "break-if-addr>"
33405     0xe/imm32/size
33406     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/>
33407 _string-break-if-addr>=:  # (payload array byte)
33408     0x11/imm32/alloc-id:fake:payload
33409     # "break-if-addr>="
33410     0xf/imm32/size
33411     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/=
33412 _string-break-if-float<:  # (payload array byte)
33413     0x11/imm32/alloc-id:fake:payload
33414     # "break-if-float<"
33415     0xf/imm32/size
33416     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/<
33417 _string-break-if-float<=:  # (payload array byte)
33418     0x11/imm32/alloc-id:fake:payload
33419     # "break-if-float<="
33420     0x10/imm32/size
33421     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/=
33422 _string-break-if-float>:  # (payload array byte)
33423     0x11/imm32/alloc-id:fake:payload
33424     # "break-if-float>"
33425     0xf/imm32/size
33426     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/>
33427 _string-break-if-float>=:  # (payload array byte)
33428     0x11/imm32/alloc-id:fake:payload
33429     # "break-if-float>="
33430     0x10/imm32/size
33431     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/=
33432 _string-compare:  # (payload array byte)
33433     0x11/imm32/alloc-id:fake:payload
33434     # "compare"
33435     0x7/imm32/size
33436     0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e
33437 _string-copy:  # (payload array byte)
33438     0x11/imm32/alloc-id:fake:payload
33439     # "copy"
33440     0x4/imm32/size
33441     0x63/c 0x6f/o 0x70/p 0x79/y
33442 _string-copy-to:  # (payload array byte)
33443     0x11/imm32/alloc-id:fake:payload
33444     # "copy-to"
33445     0x7/imm32/size
33446     0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/dash 0x74/t 0x6f/o
33447 _string-copy-byte:
33448     0x11/imm32/alloc-id:fake:payload
33449     # "copy-byte"
33450     0x9/imm32/size
33451     0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/- 0x62/b 0x79/y 0x74/t 0x65/e
33452 _string-copy-byte-to:
33453     0x11/imm32/alloc-id:fake:payload
33454     # "copy-byte-to"
33455     0xc/imm32/size
33456     0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/- 0x62/b 0x79/y 0x74/t 0x65/e 0x2d/- 0x74/t 0x6f/o
33457 _string-decrement:  # (payload array byte)
33458     0x11/imm32/alloc-id:fake:payload
33459     # "decrement"
33460     0x9/imm32/size
33461     0x64/d 0x65/e 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t
33462 _string-increment:  # (payload array byte)
33463     0x11/imm32/alloc-id:fake:payload
33464     # "increment"
33465     0x9/imm32/size
33466     0x69/i 0x6e/n 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t
33467 _string-loop:  # (payload array byte)
33468     0x11/imm32/alloc-id:fake:payload
33469     # "loop"
33470     0x4/imm32/size
33471     0x6c/l 0x6f/o 0x6f/o 0x70/p
33472 _string-loop-if-<:  # (payload array byte)
33473     0x11/imm32/alloc-id:fake:payload
33474     # "loop-if-<"
33475     0x9/imm32/size
33476     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/<
33477 _string-loop-if-<=:  # (payload array byte)
33478     0x11/imm32/alloc-id:fake:payload
33479     # "loop-if-<="
33480     0xa/imm32/size
33481     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< 0x3d/=
33482 _string-loop-if-=:  # (payload array byte)
33483     0x11/imm32/alloc-id:fake:payload
33484     # "loop-if-="
33485     0x9/imm32/size
33486     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3d/=
33487 _string-loop-if->:  # (payload array byte)
33488     0x11/imm32/alloc-id:fake:payload
33489     # "loop-if->"
33490     0x9/imm32/size
33491     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/>
33492 _string-loop-if->=:  # (payload array byte)
33493     0x11/imm32/alloc-id:fake:payload
33494     # "loop-if->="
33495     0xa/imm32/size
33496     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> 0x3d/=
33497 _string-loop-if-!=:  # (payload array byte)
33498     0x11/imm32/alloc-id:fake:payload
33499     # "loop-if-!="
33500     0xa/imm32/size
33501     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x21/! 0x3d/=
33502 _string-loop-if-addr<:  # (payload array byte)
33503     0x11/imm32/alloc-id:fake:payload
33504     # "loop-if-addr<"
33505     0xd/imm32/size
33506     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/<
33507 _string-loop-if-addr<=:  # (payload array byte)
33508     0x11/imm32/alloc-id:fake:payload
33509     # "loop-if-addr<="
33510     0xe/imm32/size
33511     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/=
33512 _string-loop-if-addr>:  # (payload array byte)
33513     0x11/imm32/alloc-id:fake:payload
33514     # "loop-if-addr>"
33515     0xd/imm32/size
33516     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/>
33517 _string-loop-if-addr>=:  # (payload array byte)
33518     0x11/imm32/alloc-id:fake:payload
33519     # "loop-if-addr>="
33520     0xe/imm32/size
33521     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/=
33522 _string-loop-if-float<:  # (payload array byte)
33523     0x11/imm32/alloc-id:fake:payload
33524     # "loop-if-float<"
33525     0xe/imm32/size
33526     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/<
33527 _string-loop-if-float<=:  # (payload array byte)
33528     0x11/imm32/alloc-id:fake:payload
33529     # "loop-if-float<="
33530     0xf/imm32/size
33531     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/=
33532 _string-loop-if-float>:  # (payload array byte)
33533     0x11/imm32/alloc-id:fake:payload
33534     # "loop-if-float>"
33535     0xe/imm32/size
33536     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/>
33537 _string-loop-if-float>=:  # (payload array byte)
33538     0x11/imm32/alloc-id:fake:payload
33539     # "loop-if-float>="
33540     0xf/imm32/size
33541     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/=
33542 _string-multiply:  # (payload array byte)
33543     0x11/imm32/alloc-id:fake:payload
33544     # "multiply"
33545     0x8/imm32/size
33546     0x6d/m 0x75/u 0x6c/l 0x74/t 0x69/i 0x70/p 0x6c/l 0x79/y
33547 _string-convert:  # (payload array byte)
33548     0x11/imm32/alloc-id:fake:payload
33549     # "convert"
33550     0x7/imm32/size
33551     0x63/c 0x6f/o 0x6e/n 0x76/v 0x65/e 0x72/r 0x74/t
33552 _string-truncate:  # (payload array byte)
33553     0x11/imm32/alloc-id:fake:payload
33554     # "truncate"
33555     0x8/imm32/size
33556     0x74/t 0x72/r 0x75/u 0x6e/n 0x63/c 0x61/a 0x74/t 0x65/e
33557 _string-reinterpret:  # (payload array byte)
33558     0x11/imm32/alloc-id:fake:payload
33559     # "reinterpret"
33560     0xb/imm32/size
33561     0x72/r 0x65/e 0x69/i 0x6e/n 0x74/t 0x65/e 0x72/r 0x70/p 0x72/r 0x65/e 0x74/t
33562 _string-divide:
33563     0x11/imm32/alloc-id:fake:payload
33564     # "divide"
33565     0x6/imm32/size
33566     0x64/d 0x69/i 0x76/v 0x69/i 0x64/d 0x65/e
33567 _string-max:
33568     0x11/imm32/alloc-id:fake:payload
33569     # "max"
33570     0x3/imm32/size
33571     0x6d/m 0x61/a 0x78/x
33572 _string-min:
33573     0x11/imm32/alloc-id:fake:payload
33574     # "min"
33575     0x3/imm32/size
33576     0x6d/m 0x69/i 0x6e/n
33577 _string-reciprocal:
33578     0x11/imm32/alloc-id:fake:payload
33579     # "reciprocal"
33580     0xa/imm32/size
33581     0x72/r 0x65/e 0x63/c 0x69/i 0x70/p 0x72/r 0x6f/o 0x63/c 0x61/a 0x6c/l
33582 _string-square-root:
33583     0x11/imm32/alloc-id:fake:payload
33584     # "square-root"
33585     0xb/imm32/size
33586     0x73/s 0x71/q 0x75/u 0x61/a 0x72/r 0x65/e 0x2d/- 0x72/r 0x6f/o 0x6f/o 0x74/t
33587 _string-inverse-square-root:
33588     0x11/imm32/alloc-id:fake:payload
33589     # "inverse-square-root"
33590     0x13/imm32/size
33591     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
33592 _string-negate:  # (payload array byte)
33593     0x11/imm32/alloc-id:fake:payload
33594     # "negate"
33595     0x6/imm32/size
33596     0x6e/n 0x65/e 0x67/g 0x61/a 0x74/t 0x65/e
33597 _string-or:  # (payload array byte)
33598     0x11/imm32/alloc-id:fake:payload
33599     # "or"
33600     0x2/imm32/size
33601     0x6f/o 0x72/r
33602 _string-or-with:  # (payload array byte)
33603     0x11/imm32/alloc-id:fake:payload
33604     # "or-with"
33605     0x7/imm32/size
33606     0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
33607 _string-subtract:  # (payload array byte)
33608     0x11/imm32/alloc-id:fake:payload
33609     # "subtract"
33610     0x8/imm32/size
33611     0x73/s 0x75/u 0x62/b 0x74/t 0x72/r 0x61/a 0x63/c 0x74/t
33612 _string-subtract-from:  # (payload array byte)
33613     0x11/imm32/alloc-id:fake:payload
33614     # "subtract-from"
33615     0xd/imm32/size
33616     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
33617 _string-xor:  # (payload array byte)
33618     0x11/imm32/alloc-id:fake:payload
33619     # "xor"
33620     0x3/imm32/size
33621     0x78/x 0x6f/o 0x72/r
33622 _string-xor-with:  # (payload array byte)
33623     0x11/imm32/alloc-id:fake:payload
33624     # "xor-with"
33625     0x8/imm32/size
33626     0x78/x 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
33627 _string-shift-left:  # (payload array byte)
33628     0x11/imm32/alloc-id:fake:payload
33629     # "shift-left"
33630     0xa/imm32/size
33631     0x73/s 0x68/h 0x69/i 0x66/f 0x74/t 0x2d/dash 0x6c/l 0x65/e 0x66/f 0x74/t
33632 _string-shift-right:  # (payload array byte)
33633     0x11/imm32/alloc-id:fake:payload
33634     # "shift-right"
33635     0xb/imm32/size
33636     0x73/s 0x68/h 0x69/i 0x66/f 0x74/t 0x2d/dash 0x72/r 0x69/i 0x67/g 0x68/h 0x74/t
33637 _string-shift-right-signed:  # (payload array byte)
33638     0x11/imm32/alloc-id:fake:payload
33639     # "shift-right-signed"
33640     0x12/imm32/size
33641     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
33642 
33643 # string literals for SubX instructions
33644 _string_01_add_to:  # (payload array byte)
33645     0x11/imm32/alloc-id:fake:payload
33646     # "01/add-to"
33647     0x9/imm32/size
33648     0x30/0 0x31/1 0x2f/slash 0x61/a 0x64/d 0x64/d 0x2d/dash 0x74/t 0x6f/o
33649 _string_03_add:  # (payload array byte)
33650     0x11/imm32/alloc-id:fake:payload
33651     # "03/add"
33652     0x6/imm32/size
33653     0x30/0 0x33/3 0x2f/slash 0x61/a 0x64/d 0x64/d
33654 _string_05_add_to_eax:  # (payload array byte)
33655     0x11/imm32/alloc-id:fake:payload
33656     # "05/add-to-eax"
33657     0xd/imm32/size
33658     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
33659 _string_09_or_with:  # (payload array byte)
33660     0x11/imm32/alloc-id:fake:payload
33661     # "09/or-with"
33662     0xa/imm32/size
33663     0x30/0 0x39/9 0x2f/slash 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
33664 _string_0b_or:  # (payload array byte)
33665     0x11/imm32/alloc-id:fake:payload
33666     # "0b/or"
33667     0x5/imm32/size
33668     0x30/0 0x62/b 0x2f/slash 0x6f/o 0x72/r
33669 _string_0d_or_with_eax:  # (payload array byte)
33670     0x11/imm32/alloc-id:fake:payload
33671     # "0d/or-with-eax"
33672     0xe/imm32/size
33673     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
33674 _string_0f_82_jump_label:  # (payload array byte)
33675     0x11/imm32/alloc-id:fake:payload
33676     # "0f 82/jump-if-addr<"
33677     0x13/imm32/size
33678     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/<
33679 _string_0f_82_jump_break:  # (payload array byte)
33680     0x11/imm32/alloc-id:fake:payload
33681     # "0f 82/jump-if-addr< break/disp32"
33682     0x20/imm32/size
33683     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
33684 _string_0f_82_jump_loop:  # (payload array byte)
33685     0x11/imm32/alloc-id:fake:payload
33686     # "0f 82/jump-if-addr< loop/disp32"
33687     0x1f/imm32/size
33688     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
33689 _string_0f_83_jump_label:  # (payload array byte)
33690     0x11/imm32/alloc-id:fake:payload
33691     # "0f 83/jump-if-addr>="
33692     0x14/imm32/size
33693     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/=
33694 _string_0f_83_jump_break:  # (payload array byte)
33695     0x11/imm32/alloc-id:fake:payload
33696     # "0f 83/jump-if-addr>= break/disp32"
33697     0x21/imm32/size
33698     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
33699 _string_0f_83_jump_loop:  # (payload array byte)
33700     0x11/imm32/alloc-id:fake:payload
33701     # "0f 83/jump-if-addr>= loop/disp32"
33702     0x20/imm32/size
33703     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
33704 _string_0f_84_jump_label:  # (payload array byte)
33705     0x11/imm32/alloc-id:fake:payload
33706     # "0f 84/jump-if-="
33707     0xf/imm32/size
33708     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/=
33709 _string_0f_84_jump_break:  # (payload array byte)
33710     0x11/imm32/alloc-id:fake:payload
33711     # "0f 84/jump-if-= break/disp32"
33712     0x1c/imm32/size
33713     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
33714 _string_0f_84_jump_loop:  # (payload array byte)
33715     0x11/imm32/alloc-id:fake:payload
33716     # "0f 84/jump-if-= loop/disp32"
33717     0x1b/imm32/size
33718     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
33719 _string_0f_85_jump_label:  # (payload array byte)
33720     0x11/imm32/alloc-id:fake:payload
33721     # "0f 85/jump-if-!="
33722     0x10/imm32/size
33723     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/=
33724 _string_0f_85_jump_break:  # (payload array byte)
33725     0x11/imm32/alloc-id:fake:payload
33726     # "0f 85/jump-if-!= break/disp32"
33727     0x1d/imm32/size
33728     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
33729 _string_0f_85_jump_loop:  # (payload array byte)
33730     0x11/imm32/alloc-id:fake:payload
33731     # "0f 85/jump-if-!= loop/disp32"
33732     0x1c/imm32/size
33733     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
33734 _string_0f_86_jump_label:  # (payload array byte)
33735     0x11/imm32/alloc-id:fake:payload
33736     # "0f 86/jump-if-addr<="
33737     0x14/imm32/size
33738     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/=
33739 _string_0f_86_jump_break:  # (payload array byte)
33740     0x11/imm32/alloc-id:fake:payload
33741     # "0f 86/jump-if-addr<= break/disp32"
33742     0x21/imm32/size
33743     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
33744 _string_0f_86_jump_loop:  # (payload array byte)
33745     0x11/imm32/alloc-id:fake:payload
33746     # "0f 86/jump-if-addr<= loop/disp32"
33747     0x20/imm32/size
33748     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
33749 _string_0f_87_jump_label:  # (payload array byte)
33750     0x11/imm32/alloc-id:fake:payload
33751     # "0f 87/jump-if-addr>"
33752     0x13/imm32/size
33753     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/>
33754 _string_0f_87_jump_break:  # (payload array byte)
33755     0x11/imm32/alloc-id:fake:payload
33756     # "0f 87/jump-if-addr> break/disp32"
33757     0x20/imm32/size
33758     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
33759 _string_0f_87_jump_loop:  # (payload array byte)
33760     0x11/imm32/alloc-id:fake:payload
33761     # "0f 87/jump-if-addr> loop/disp32"
33762     0x1f/imm32/size
33763     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
33764 _string_0f_8c_jump_label:  # (payload array byte)
33765     0x11/imm32/alloc-id:fake:payload
33766     # "0f 8c/jump-if-<"
33767     0xf/imm32/size
33768     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/<
33769 _string_0f_8c_jump_break:  # (payload array byte)
33770     0x11/imm32/alloc-id:fake:payload
33771     # "0f 8c/jump-if-< break/disp32"
33772     0x1c/imm32/size
33773     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
33774 _string_0f_8c_jump_loop:  # (payload array byte)
33775     0x11/imm32/alloc-id:fake:payload
33776     # "0f 8c/jump-if-< loop/disp32"
33777     0x1b/imm32/size
33778     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
33779 _string_0f_8d_jump_label:  # (payload array byte)
33780     0x11/imm32/alloc-id:fake:payload
33781     # "0f 8d/jump-if->="
33782     0x10/imm32/size
33783     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/=
33784 _string_0f_8d_jump_break:  # (payload array byte)
33785     0x11/imm32/alloc-id:fake:payload
33786     # "0f 8d/jump-if->= break/disp32"
33787     0x1d/imm32/size
33788     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
33789 _string_0f_8d_jump_loop:  # (payload array byte)
33790     0x11/imm32/alloc-id:fake:payload
33791     # "0f 8d/jump-if->= loop/disp32"
33792     0x1c/imm32/size
33793     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
33794 _string_0f_8e_jump_label:  # (payload array byte)
33795     0x11/imm32/alloc-id:fake:payload
33796     # "0f 8e/jump-if-<="
33797     0x10/imm32/size
33798     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/=
33799 _string_0f_8e_jump_break:  # (payload array byte)
33800     0x11/imm32/alloc-id:fake:payload
33801     # "0f 8e/jump-if-<= break/disp32"
33802     0x1d/imm32/size
33803     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
33804 _string_0f_8e_jump_loop:  # (payload array byte)
33805     0x11/imm32/alloc-id:fake:payload
33806     # "0f 8e/jump-if-<= loop/disp32"
33807     0x1c/imm32/size
33808     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
33809 _string_0f_8f_jump_label:  # (payload array byte)
33810     0x11/imm32/alloc-id:fake:payload
33811     # "0f 8f/jump-if->"
33812     0xf/imm32/size
33813     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/>
33814 _string_0f_8f_jump_break:  # (payload array byte)
33815     0x11/imm32/alloc-id:fake:payload
33816     # "0f 8f/jump-if-> break/disp32"
33817     0x1c/imm32/size
33818     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
33819 _string_0f_8f_jump_loop:  # (payload array byte)
33820     0x11/imm32/alloc-id:fake:payload
33821     # "0f 8f/jump-if-> loop/disp32"
33822     0x1b/imm32/size
33823     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
33824 _string_0f_af_multiply:  # (payload array byte)
33825     0x11/imm32/alloc-id:fake:payload
33826     # "0f af/multiply"
33827     0xe/imm32/size
33828     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
33829 _string_f3_0f_2a_convert_to_float:
33830     0x11/imm32/alloc-id:fake:payload
33831     # "f3 0f 2a/convert-to-float"
33832     0x19/imm32/size
33833     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
33834 _string_f3_0f_2d_convert_to_int:
33835     0x11/imm32/alloc-id:fake:payload
33836     # "f3 0f 2d/convert-to-int"
33837     0x17/imm32/size
33838     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
33839 _string_f3_0f_2c_truncate_to_int:
33840     0x11/imm32/alloc-id:fake:payload
33841     # "f3 0f 2c/truncate-to-int"
33842     0x18/imm32/size
33843     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
33844 _string_f3_0f_58_add:
33845     0x11/imm32/alloc-id:fake:payload
33846     # "f3 0f 58/add"
33847     0xc/imm32/size
33848     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x38/8 0x2f/slash 0x61/a 0x64/d 0x64/d
33849 _string_f3_0f_5c_subtract:
33850     0x11/imm32/alloc-id:fake:payload
33851     # "f3 0f 5c/subtract"
33852     0x11/imm32/size
33853     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
33854 _string_f3_0f_59_multiply:
33855     0x11/imm32/alloc-id:fake:payload
33856     # "f3 0f 59/multiply"
33857     0x11/imm32/size
33858     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
33859 _string_f3_0f_5e_divide:
33860     0x11/imm32/alloc-id:fake:payload
33861     # "f3 0f 5e/divide"
33862     0xf/imm32/size
33863     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
33864 _string_f3_0f_53_reciprocal:
33865     0x11/imm32/alloc-id:fake:payload
33866     # "f3 0f 53/reciprocal"
33867     0x13/imm32/size
33868     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
33869 _string_f3_0f_51_square_root:
33870     0x11/imm32/alloc-id:fake:payload
33871     # "f3 0f 51/square-root"
33872     0x14/imm32/size
33873     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
33874 _string_f3_0f_52_inverse_square_root:
33875     0x11/imm32/alloc-id:fake:payload
33876     # "f3 0f 52/inverse-square-root"
33877     0x1c/imm32/size
33878     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
33879 _string_f3_0f_5d_min:
33880     0x11/imm32/alloc-id:fake:payload
33881     # "f3 0f 5d/min"
33882     0xc/imm32/size
33883     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x64/d 0x2f/slash 0x6d/m 0x69/i 0x6e/n
33884 _string_f3_0f_5f_max:
33885     0x11/imm32/alloc-id:fake:payload
33886     # "f3 0f 5f/max"
33887     0xc/imm32/size
33888     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x66/f 0x2f/slash 0x6d/m 0x61/a 0x78/x
33889 _string_f3_0f_10_copy:
33890     0x11/imm32/alloc-id:fake:payload
33891     # "f3 0f 10/copy"
33892     0xd/imm32/size
33893     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
33894 _string_f3_0f_11_copy:
33895     0x11/imm32/alloc-id:fake:payload
33896     # "f3 0f 11/copy"
33897     0xd/imm32/size
33898     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
33899 _string_0f_2f_compare:
33900     0x11/imm32/alloc-id:fake:payload
33901     # "0f 2f/compare"
33902     0xd/imm32/size
33903     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
33904 _string_21_and_with:  # (payload array byte)
33905     0x11/imm32/alloc-id:fake:payload
33906     # "21/and-with"
33907     0xb/imm32/size
33908     0x32/2 0x31/1 0x2f/slash 0x61/a 0x6e/n 0x64/d 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
33909 _string_23_and:  # (payload array byte)
33910     0x11/imm32/alloc-id:fake:payload
33911     # "23/and"
33912     0x6/imm32/size
33913     0x32/2 0x33/3 0x2f/slash 0x61/a 0x6e/n 0x64/d
33914 _string_25_and_with_eax:  # (payload array byte)
33915     0x11/imm32/alloc-id:fake:payload
33916     # "25/and-with-eax"
33917     0xf/imm32/size
33918     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
33919 _string_29_subtract_from:  # (payload array byte)
33920     0x11/imm32/alloc-id:fake:payload
33921     # "29/subtract-from"
33922     0x10/imm32/size
33923     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
33924 _string_2b_subtract:  # (payload array byte)
33925     0x11/imm32/alloc-id:fake:payload
33926     # "2b/subtract"
33927     0xb/imm32/size
33928     0x32/2 0x62/b 0x2f/slash 0x73/s 0x75/u 0x62/b 0x74/t 0x72/r 0x61/a 0x63/c 0x74/t
33929 _string_2d_subtract_from_eax:  # (payload array byte)
33930     0x11/imm32/alloc-id:fake:payload
33931     # "2d/subtract-from-eax"
33932     0x14/imm32/size
33933     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
33934 _string_31_xor_with:  # (payload array byte)
33935     0x11/imm32/alloc-id:fake:payload
33936     # "31/xor-with"
33937     0xb/imm32/size
33938     0x33/3 0x31/1 0x2f/slash 0x78/x 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
33939 _string_33_xor:  # (payload array byte)
33940     0x11/imm32/alloc-id:fake:payload
33941     # "33/xor"
33942     0x6/imm32/size
33943     0x33/3 0x33/3 0x2f/slash 0x78/x 0x6f/o 0x72/r
33944 _string_35_xor_with_eax:  # (payload array byte)
33945     0x11/imm32/alloc-id:fake:payload
33946     # "35/xor-with-eax"
33947     0xf/imm32/size
33948     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
33949 _string_39_compare->:  # (payload array byte)
33950     0x11/imm32/alloc-id:fake:payload
33951     # "39/compare->"
33952     0xc/imm32/size
33953     0x33/3 0x39/9 0x2f/slash 0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e 0x2d/dash 0x3e/>
33954 _string_3b_compare<-:  # (payload array byte)
33955     0x11/imm32/alloc-id:fake:payload
33956     # "3b/compare<-"
33957     0xc/imm32/size
33958     0x33/3 0x62/b 0x2f/slash 0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e 0x3c/< 0x2d/dash
33959 _string_3d_compare_eax_with:  # (payload array byte)
33960     0x11/imm32/alloc-id:fake:payload
33961     # "3d/compare-eax-with"
33962     0x13/imm32/size
33963     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
33964 _string_40_increment_eax:  # (payload array byte)
33965     0x11/imm32/alloc-id:fake:payload
33966     # "40/increment-eax"
33967     0x10/imm32/size
33968     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
33969 _string_41_increment_ecx:  # (payload array byte)
33970     0x11/imm32/alloc-id:fake:payload
33971     # "41/increment-ecx"
33972     0x10/imm32/size
33973     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
33974 _string_42_increment_edx:  # (payload array byte)
33975     0x11/imm32/alloc-id:fake:payload
33976     # "42/increment-edx"
33977     0x10/imm32/size
33978     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
33979 _string_43_increment_ebx:  # (payload array byte)
33980     0x11/imm32/alloc-id:fake:payload
33981     # "43/increment-ebx"
33982     0x10/imm32/size
33983     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
33984 _string_46_increment_esi:  # (payload array byte)
33985     0x11/imm32/alloc-id:fake:payload
33986     # "46/increment-esi"
33987     0x10/imm32/size
33988     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
33989 _string_47_increment_edi:  # (payload array byte)
33990     0x11/imm32/alloc-id:fake:payload
33991     # "47/increment-edi"
33992     0x10/imm32/size
33993     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
33994 _string_48_decrement_eax:  # (payload array byte)
33995     0x11/imm32/alloc-id:fake:payload
33996     # "48/decrement-eax"
33997     0x10/imm32/size
33998     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
33999 _string_49_decrement_ecx:  # (payload array byte)
34000     0x11/imm32/alloc-id:fake:payload
34001     # "49/decrement-ecx"
34002     0x10/imm32/size
34003     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
34004 _string_4a_decrement_edx:  # (payload array byte)
34005     0x11/imm32/alloc-id:fake:payload
34006     # "4a/decrement-edx"
34007     0x10/imm32/size
34008     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
34009 _string_4b_decrement_ebx:  # (payload array byte)
34010     0x11/imm32/alloc-id:fake:payload
34011     # "4b/decrement-ebx"
34012     0x10/imm32/size
34013     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
34014 _string_4e_decrement_esi:  # (payload array byte)
34015     0x11/imm32/alloc-id:fake:payload
34016     # "4e/decrement-esi"
34017     0x10/imm32/size
34018     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
34019 _string_4f_decrement_edi:  # (payload array byte)
34020     0x11/imm32/alloc-id:fake:payload
34021     # "4f/decrement-edi"
34022     0x10/imm32/size
34023     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
34024 _string_81_subop_add:  # (payload array byte)
34025     0x11/imm32/alloc-id:fake:payload
34026     # "81 0/subop/add"
34027     0xe/imm32/size
34028     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
34029 _string_81_subop_or:  # (payload array byte)
34030     0x11/imm32/alloc-id:fake:payload
34031     # "81 1/subop/or"
34032     0xd/imm32/size
34033     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
34034 _string_81_subop_and:  # (payload array byte)
34035     0x11/imm32/alloc-id:fake:payload
34036     # "81 4/subop/and"
34037     0xe/imm32/size
34038     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
34039 _string_81_subop_subtract:  # (payload array byte)
34040     0x11/imm32/alloc-id:fake:payload
34041     # "81 5/subop/subtract"
34042     0x13/imm32/size
34043     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
34044 _string_81_subop_xor:  # (payload array byte)
34045     0x11/imm32/alloc-id:fake:payload
34046     # "81 6/subop/xor"
34047     0xe/imm32/size
34048     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
34049 _string_81_subop_compare:  # (payload array byte)
34050     0x11/imm32/alloc-id:fake:payload
34051     # "81 7/subop/compare"
34052     0x12/imm32/size
34053     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
34054 _string_89_<-:  # (payload array byte)
34055     0x11/imm32/alloc-id:fake:payload
34056     # "89/<-"
34057     0x5/imm32/size
34058     0x38/8 0x39/9 0x2f/slash 0x3c/< 0x2d/dash
34059 _string_8b_->:  # (payload array byte)
34060     0x11/imm32/alloc-id:fake:payload
34061     # "8b/->"
34062     0x5/imm32/size
34063     0x38/8 0x62/b 0x2f/slash 0x2d/dash 0x3e/>
34064 _string_8a_copy_byte:
34065     0x11/imm32/alloc-id:fake:payload
34066     # "8a/byte->"
34067     0x9/imm32/size
34068     0x38/8 0x61/a 0x2f// 0x62/b 0x79/y 0x74/t 0x65/e 0x2d/- 0x3e/>
34069 _string_88_copy_byte:
34070     0x11/imm32/alloc-id:fake:payload
34071     # "88/byte<-"
34072     0x9/imm32/size
34073     0x38/8 0x38/8 0x2f// 0x62/b 0x79/y 0x74/t 0x65/e 0x3c/< 0x2d/-
34074 _string_8d_copy_address:  # (payload array byte)
34075     0x11/imm32/alloc-id:fake:payload
34076     # "8d/copy-address"
34077     0xf/imm32/size
34078     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
34079 _string_b8_copy_to_eax:  # (payload array byte)
34080     0x11/imm32/alloc-id:fake:payload
34081     # "b8/copy-to-eax"
34082     0xe/imm32/size
34083     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
34084 _string_b9_copy_to_ecx:  # (payload array byte)
34085     0x11/imm32/alloc-id:fake:payload
34086     # "b9/copy-to-ecx"
34087     0xe/imm32/size
34088     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
34089 _string_ba_copy_to_edx:  # (payload array byte)
34090     0x11/imm32/alloc-id:fake:payload
34091     # "ba/copy-to-edx"
34092     0xe/imm32/size
34093     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
34094 _string_bb_copy_to_ebx:  # (payload array byte)
34095     0x11/imm32/alloc-id:fake:payload
34096     # "bb/copy-to-ebx"
34097     0xe/imm32/size
34098     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
34099 _string_be_copy_to_esi:  # (payload array byte)
34100     0x11/imm32/alloc-id:fake:payload
34101     # "be/copy-to-esi"
34102     0xe/imm32/size
34103     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
34104 _string_bf_copy_to_edi:  # (payload array byte)
34105     0x11/imm32/alloc-id:fake:payload
34106     # "bf/copy-to-edi"
34107     0xe/imm32/size
34108     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
34109 _string_c7_subop_copy:  # (payload array byte)
34110     0x11/imm32/alloc-id:fake:payload
34111     # "c7 0/subop/copy"
34112     0xf/imm32/size
34113     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
34114 _string_e9_jump_label:  # (payload array byte)
34115     0x11/imm32/alloc-id:fake:payload
34116     # "e9/jump"
34117     0x7/imm32/size
34118     0x65/e 0x39/9 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p
34119 _string_e9_jump_break:  # (payload array byte)
34120     0x11/imm32/alloc-id:fake:payload
34121     # "e9/jump break/disp32"
34122     0x14/imm32/size
34123     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
34124 _string_e9_jump_loop:  # (payload array byte)
34125     0x11/imm32/alloc-id:fake:payload
34126     # "e9/jump loop/disp32"
34127     0x13/imm32/size
34128     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
34129 _string_f7_subop_negate:
34130     0x11/imm32/alloc-id:fake:payload
34131     # "f7 3/subop/negate"
34132     0x11/imm32/size
34133     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
34134 _string_ff_subop_increment:  # (payload array byte)
34135     0x11/imm32/alloc-id:fake:payload
34136     # "ff 0/subop/increment"
34137     0x14/imm32/size
34138     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
34139 _string_ff_subop_decrement:  # (payload array byte)
34140     0x11/imm32/alloc-id:fake:payload
34141     # "ff 1/subop/decrement"
34142     0x14/imm32/size
34143     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
34144 _string_c1_subop_shift_left:  # (payload array byte)
34145     0x11/imm32/alloc-id:fake:payload
34146     # "c1/shift 4/subop/left"
34147     0x15/imm32/size
34148     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
34149 _string_c1_subop_shift_right_padding_zeroes:  # (payload array byte)
34150     0x11/imm32/alloc-id:fake:payload
34151     # "c1/shift 5/subop/right-padding-zeroes"
34152     0x25/imm32/size
34153     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
34154 _string_c1_subop_shift_right_preserving_sign:  # (payload array byte)
34155     0x11/imm32/alloc-id:fake:payload
34156     # "c1/shift 7/subop/right-preserving-sign"
34157     0x26/imm32/size
34158     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
34159 
34160 Single-int-var-in-mem:  # (payload list var)
34161     0x11/imm32/alloc-id:fake:payload
34162     0x11/imm32/alloc-id:fake
34163     Int-var-in-mem/imm32
34164     0/imm32/next
34165     0/imm32/next
34166 
34167 Int-var-in-mem:  # (payload var)
34168     0x11/imm32/alloc-id:fake:payload
34169     0/imm32/name
34170     0/imm32/name
34171     0x11/imm32/alloc-id:fake
34172     Type-int/imm32
34173     1/imm32/some-block-depth
34174     1/imm32/some-stack-offset
34175     0/imm32/no-register
34176     0/imm32/no-register
34177 
34178 # Not really legal, but closest we can currently represent a dereference of an (addr byte)
34179 Single-byte-var-in-mem:  # (payload list var)
34180     0x11/imm32/alloc-id:fake:payload
34181     0x11/imm32/alloc-id:fake
34182     Byte-var-in-mem/imm32
34183     0/imm32/next
34184     0/imm32/next
34185 
34186 # Not really legal, but closest we can currently represent a dereference of an (addr byte)
34187 Byte-var-in-mem:  # (payload var)
34188     0x11/imm32/alloc-id:fake:payload
34189     0/imm32/name
34190     0/imm32/name
34191     0x11/imm32/alloc-id:fake
34192     Type-byte/imm32
34193     1/imm32/some-block-depth
34194     1/imm32/some-stack-offset
34195     0/imm32/no-register
34196     0/imm32/no-register
34197 
34198 Two-args-int-stack-int-reg:  # (payload list var)
34199     0x11/imm32/alloc-id:fake:payload
34200     0x11/imm32/alloc-id:fake
34201     Int-var-in-mem/imm32
34202     0x11/imm32/alloc-id:fake
34203     Single-int-var-in-some-register/imm32/next
34204 
34205 Two-int-args-in-regs:  # (payload list var)
34206     0x11/imm32/alloc-id:fake:payload
34207     0x11/imm32/alloc-id:fake
34208     Int-var-in-some-register/imm32
34209     0x11/imm32/alloc-id:fake
34210     Single-int-var-in-some-register/imm32/next
34211 
34212 # Not really legal, but closest we can currently represent a dereference of an (addr byte)
34213 Two-args-byte-stack-byte-reg:  # (payload list var)
34214     0x11/imm32/alloc-id:fake:payload
34215     0x11/imm32/alloc-id:fake
34216     Byte-var-in-mem/imm32
34217     0x11/imm32/alloc-id:fake
34218     Single-byte-var-in-some-register/imm32/next
34219 
34220 Two-args-int-reg-int-stack:  # (payload list var)
34221     0x11/imm32/alloc-id:fake:payload
34222     0x11/imm32/alloc-id:fake
34223     Int-var-in-some-register/imm32
34224     0x11/imm32/alloc-id:fake
34225     Single-int-var-in-mem/imm32/next
34226 
34227 Two-args-int-eax-int-literal:  # (payload list var)
34228     0x11/imm32/alloc-id:fake:payload
34229     0x11/imm32/alloc-id:fake
34230     Int-var-in-eax/imm32
34231     0x11/imm32/alloc-id:fake
34232     Single-lit-var/imm32/next
34233 
34234 Int-var-and-literal:  # (payload list var)
34235     0x11/imm32/alloc-id:fake:payload
34236     0x11/imm32/alloc-id:fake
34237     Int-var-in-mem/imm32
34238     0x11/imm32/alloc-id:fake
34239     Single-lit-var/imm32/next
34240 
34241 Int-var-in-register-and-literal:  # (payload list var)
34242     0x11/imm32/alloc-id:fake:payload
34243     0x11/imm32/alloc-id:fake
34244     Int-var-in-some-register/imm32
34245     0x11/imm32/alloc-id:fake
34246     Single-lit-var/imm32/next
34247 
34248 Two-float-args-in-regs:  # (payload list var)
34249     0x11/imm32/alloc-id:fake:payload
34250     0x11/imm32/alloc-id:fake
34251     Float-var-in-some-register/imm32
34252     0x11/imm32/alloc-id:fake
34253     Single-float-var-in-some-register/imm32/next
34254 
34255 Two-args-float-reg-float-stack:  # (payload list var)
34256     0x11/imm32/alloc-id:fake:payload
34257     0x11/imm32/alloc-id:fake
34258     Float-var-in-some-register/imm32
34259     0x11/imm32/alloc-id:fake
34260     Single-float-var-in-mem/imm32/next
34261 
34262 Two-args-float-stack-float-reg:  # (payload list var)
34263     0x11/imm32/alloc-id:fake:payload
34264     0x11/imm32/alloc-id:fake
34265     Float-var-in-mem/imm32
34266     0x11/imm32/alloc-id:fake
34267     Single-float-var-in-some-register/imm32/next
34268 
34269 Single-int-var-in-some-register:  # (payload list var)
34270     0x11/imm32/alloc-id:fake:payload
34271     0x11/imm32/alloc-id:fake
34272     Int-var-in-some-register/imm32
34273     0/imm32/next
34274     0/imm32/next
34275 
34276 Single-addr-var-in-some-register:  # (payload list var)
34277     0x11/imm32/alloc-id:fake:payload
34278     0x11/imm32/alloc-id:fake
34279     Addr-var-in-some-register/imm32
34280     0/imm32/next
34281     0/imm32/next
34282 
34283 Single-byte-var-in-some-register:  # (payload list var)
34284     0x11/imm32/alloc-id:fake:payload
34285     0x11/imm32/alloc-id:fake
34286     Byte-var-in-some-register/imm32
34287     0/imm32/next
34288     0/imm32/next
34289 
34290 Int-var-in-some-register:  # (payload var)
34291     0x11/imm32/alloc-id:fake:payload
34292     0/imm32/name
34293     0/imm32/name
34294     0x11/imm32/alloc-id:fake
34295     Type-int/imm32
34296     1/imm32/some-block-depth
34297     0/imm32/no-stack-offset
34298     0x11/imm32/alloc-id:fake
34299     Any-register/imm32
34300 
34301 Any-register:  # (payload array byte)
34302     0x11/imm32/alloc-id:fake:payload
34303     1/imm32/size
34304     # data
34305     2a/asterisk
34306 
34307 Addr-var-in-some-register:  # (payload var)
34308     0x11/imm32/alloc-id:fake:payload
34309     0/imm32/name
34310     0/imm32/name
34311     0x11/imm32/alloc-id:fake
34312     Type-addr/imm32
34313     1/imm32/some-block-depth
34314     0/imm32/no-stack-offset
34315     0x11/imm32/alloc-id:fake
34316     Any-register/imm32
34317 
34318 Byte-var-in-some-register:  # (payload var)
34319     0x11/imm32/alloc-id:fake:payload
34320     0/imm32/name
34321     0/imm32/name
34322     0x11/imm32/alloc-id:fake
34323     Type-byte/imm32
34324     1/imm32/some-block-depth
34325     0/imm32/no-stack-offset
34326     0x11/imm32/alloc-id:fake
34327     Any-register/imm32
34328 
34329 Single-int-var-in-eax:  # (payload list var)
34330     0x11/imm32/alloc-id:fake:payload
34331     0x11/imm32/alloc-id:fake
34332     Int-var-in-eax/imm32
34333     0/imm32/next
34334     0/imm32/next
34335 
34336 Int-var-in-eax:
34337     0x11/imm32/alloc-id:fake:payload
34338     0/imm32/name
34339     0/imm32/name
34340     0x11/imm32/alloc-id:fake
34341     Type-int/imm32
34342     1/imm32/some-block-depth
34343     0/imm32/no-stack-offset
34344     0x11/imm32/alloc-id:fake
34345     $Mu-register-eax/imm32  # can't use Register-eax only to keep our buggy tools/treeshake.cc happy (TODO)
34346 
34347 Single-int-var-in-ecx:  # (payload list var)
34348     0x11/imm32/alloc-id:fake:payload
34349     0x11/imm32/alloc-id:fake
34350     Int-var-in-ecx/imm32
34351     0/imm32/next
34352     0/imm32/next
34353 
34354 Int-var-in-ecx:
34355     0x11/imm32/alloc-id:fake:payload
34356     0/imm32/name
34357     0/imm32/name
34358     0x11/imm32/alloc-id:fake
34359     Type-int/imm32
34360     1/imm32/some-block-depth
34361     0/imm32/no-stack-offset
34362     0x11/imm32/alloc-id:fake
34363     $Register-ecx/imm32/register
34364 
34365 Single-int-var-in-edx:  # (payload list var)
34366     0x11/imm32/alloc-id:fake:payload
34367     0x11/imm32/alloc-id:fake
34368     Int-var-in-edx/imm32
34369     0/imm32/next
34370     0/imm32/next
34371 
34372 Int-var-in-edx:  # (payload list var)
34373     0x11/imm32/alloc-id:fake:payload
34374     0/imm32/name
34375     0/imm32/name
34376     0x11/imm32/alloc-id:fake
34377     Type-int/imm32
34378     1/imm32/some-block-depth
34379     0/imm32/no-stack-offset
34380     0x11/imm32/alloc-id:fake
34381     $Register-edx/imm32/register
34382 
34383 Single-int-var-in-ebx:  # (payload list var)
34384     0x11/imm32/alloc-id:fake:payload
34385     0x11/imm32/alloc-id:fake
34386     Int-var-in-ebx/imm32
34387     0/imm32/next
34388     0/imm32/next
34389 
34390 Int-var-in-ebx:  # (payload list var)
34391     0x11/imm32/alloc-id:fake:payload
34392     0/imm32/name
34393     0/imm32/name
34394     0x11/imm32/alloc-id:fake
34395     Type-int/imm32
34396     1/imm32/some-block-depth
34397     0/imm32/no-stack-offset
34398     0x11/imm32/alloc-id:fake
34399     $Register-ebx/imm32/register
34400 
34401 Single-int-var-in-esi:  # (payload list var)
34402     0x11/imm32/alloc-id:fake:payload
34403     0x11/imm32/alloc-id:fake
34404     Int-var-in-esi/imm32
34405     0/imm32/next
34406     0/imm32/next
34407 
34408 Int-var-in-esi:  # (payload list var)
34409     0x11/imm32/alloc-id:fake:payload
34410     0/imm32/name
34411     0/imm32/name
34412     0x11/imm32/alloc-id:fake
34413     Type-int/imm32
34414     1/imm32/some-block-depth
34415     0/imm32/no-stack-offset
34416     0x11/imm32/alloc-id:fake
34417     $Register-esi/imm32/register
34418 
34419 Single-int-var-in-edi:  # (payload list var)
34420     0x11/imm32/alloc-id:fake:payload
34421     0x11/imm32/alloc-id:fake
34422     Int-var-in-edi/imm32
34423     0/imm32/next
34424     0/imm32/next
34425 
34426 Int-var-in-edi:  # (payload list var)
34427     0x11/imm32/alloc-id:fake:payload
34428     0/imm32/name
34429     0/imm32/name
34430     0x11/imm32/alloc-id:fake
34431     Type-int/imm32
34432     1/imm32/some-block-depth
34433     0/imm32/no-stack-offset
34434     0x11/imm32/alloc-id:fake
34435     $Register-edi/imm32/register
34436 
34437 Single-lit-var:  # (payload list var)
34438     0x11/imm32/alloc-id:fake:payload
34439     0x11/imm32/alloc-id:fake
34440     Lit-var/imm32
34441     0/imm32/next
34442     0/imm32/next
34443 
34444 Lit-var:  # (payload var)
34445     0x11/imm32/alloc-id:fake:payload
34446     0/imm32/name
34447     0/imm32/name
34448     0x11/imm32/alloc-id:fake
34449     Type-literal/imm32
34450     1/imm32/some-block-depth
34451     0/imm32/no-stack-offset
34452     0/imm32/no-register
34453     0/imm32/no-register
34454 
34455 Single-float-var-in-mem:  # (payload list var)
34456     0x11/imm32/alloc-id:fake:payload
34457     0x11/imm32/alloc-id:fake
34458     Float-var-in-mem/imm32
34459     0/imm32/next
34460     0/imm32/next
34461 
34462 Float-var-in-mem:  # (payload var)
34463     0x11/imm32/alloc-id:fake:payload
34464     0/imm32/name
34465     0/imm32/name
34466     0x11/imm32/alloc-id:fake
34467     Type-float/imm32
34468     1/imm32/some-block-depth
34469     1/imm32/some-stack-offset
34470     0/imm32/no-register
34471     0/imm32/no-register
34472 
34473 Single-float-var-in-some-register:  # (payload list var)
34474     0x11/imm32/alloc-id:fake:payload
34475     0x11/imm32/alloc-id:fake
34476     Float-var-in-some-register/imm32
34477     0/imm32/next
34478     0/imm32/next
34479 
34480 Float-var-in-some-register:  # (payload var)
34481     0x11/imm32/alloc-id:fake:payload
34482     0/imm32/name
34483     0/imm32/name
34484     0x11/imm32/alloc-id:fake
34485     Type-float/imm32
34486     1/imm32/some-block-depth
34487     0/imm32/no-stack-offset
34488     0x11/imm32/alloc-id:fake
34489     Any-register/imm32
34490 
34491 Type-int:  # (payload type-tree)
34492     0x11/imm32/alloc-id:fake:payload
34493     1/imm32/is-atom
34494     1/imm32/value:int
34495     0/imm32/left:unused
34496     0/imm32/right:null
34497     0/imm32/right:null
34498 
34499 Type-literal:  # (payload type-tree)
34500     0x11/imm32/alloc-id:fake:payload
34501     1/imm32/is-atom
34502     0/imm32/value:literal
34503     0/imm32/left:unused
34504     0/imm32/right:null
34505     0/imm32/right:null
34506 
34507 Type-addr:  # (payload type-tree)
34508     0x11/imm32/alloc-id:fake:payload
34509     1/imm32/is-atom
34510     2/imm32/value:addr
34511     0/imm32/left:unused
34512     0/imm32/right:null
34513     0/imm32/right:null
34514 
34515 Type-byte:  # (payload type-tree)
34516     0x11/imm32/alloc-id:fake:payload
34517     1/imm32/is-atom
34518     8/imm32/value:byte
34519     0/imm32/left:unused
34520     0/imm32/right:null
34521     0/imm32/right:null
34522 
34523 Type-float:  # (payload type-tree)
34524     0x11/imm32/alloc-id:fake:payload
34525     1/imm32/is-atom
34526     0xf/imm32/value:float
34527     0/imm32/left:unused
34528     0/imm32/right:null
34529     0/imm32/right:null
34530 
34531 == code
34532 emit-subx-primitive:  # out: (addr buffered-file), stmt: (addr stmt), primitive: (addr primitive), err: (addr buffered-file), ed: (addr exit-descriptor)
34533     # . prologue
34534     55/push-ebp
34535     89/<- %ebp 4/r32/esp
34536     # . save registers
34537     50/push-eax
34538     51/push-ecx
34539     # ecx = primitive
34540     8b/-> *(ebp+0x10) 1/r32/ecx
34541     # emit primitive name
34542     (emit-indent *(ebp+8) *Curr-block-depth)
34543     (lookup *(ecx+0x18) *(ecx+0x1c))  # Primitive-subx-name Primitive-subx-name => eax
34544     (write-buffered *(ebp+8) %eax)
34545     # emit rm32 if necessary
34546     (emit-subx-rm32 *(ebp+8) *(ecx+0x20) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # Primitive-subx-rm32
34547     # emit xm32 if necessary
34548     (emit-subx-rm32 *(ebp+8) *(ecx+0x34) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # Primitive-subx-xm32
34549     # emit r32 if necessary
34550     (emit-subx-r32 *(ebp+8) *(ecx+0x24) *(ebp+0xc))  # Primitive-subx-r32
34551     # emit x32 if necessary
34552     (emit-subx-x32 *(ebp+8) *(ecx+0x38) *(ebp+0xc))  # Primitive-subx-x32
34553     # emit imm32 if necessary
34554     (emit-subx-imm32 *(ebp+8) *(ecx+0x28) *(ebp+0xc))  # Primitive-subx-imm32
34555     # emit imm8 if necessary
34556     (emit-subx-imm8 *(ebp+8) *(ecx+0x2c) *(ebp+0xc))  # Primitive-subx-imm8
34557     # emit disp32 if necessary
34558     (emit-subx-disp32 *(ebp+8) *(ecx+0x30) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # Primitive-subx-disp32
34559     (write-buffered *(ebp+8) Newline)
34560 $emit-subx-primitive:end:
34561     # . restore registers
34562     59/pop-to-ecx
34563     58/pop-to-eax
34564     # . epilogue
34565     89/<- %esp 5/r32/ebp
34566     5d/pop-to-ebp
34567     c3/return
34568 
34569 emit-subx-rm32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
34570     # . prologue
34571     55/push-ebp
34572     89/<- %ebp 4/r32/esp
34573     # . save registers
34574     50/push-eax
34575     # if (l == 0) return
34576     81 7/subop/compare *(ebp+0xc) 0/imm32
34577     74/jump-if-= $emit-subx-rm32:end/disp8
34578     # var v/eax: (addr stmt-var)
34579     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # => eax
34580     (emit-subx-var-as-rm32 *(ebp+8) %eax)
34581 $emit-subx-rm32:end:
34582     # . restore registers
34583     58/pop-to-eax
34584     # . epilogue
34585     89/<- %esp 5/r32/ebp
34586     5d/pop-to-ebp
34587     c3/return
34588 
34589 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)
34590     # . prologue
34591     55/push-ebp
34592     89/<- %ebp 4/r32/esp
34593     # . save registers
34594     51/push-ecx
34595     # eax = l
34596     8b/-> *(ebp+0xc) 0/r32/eax
34597     # ecx = stmt
34598     8b/-> *(ebp+8) 1/r32/ecx
34599     # if (l == 1) return stmt->inouts
34600     {
34601       3d/compare-eax-and 1/imm32
34602       75/jump-if-!= break/disp8
34603 $get-stmt-operand-from-arg-location:1:
34604       (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
34605       eb/jump $get-stmt-operand-from-arg-location:end/disp8
34606     }
34607     # if (l == 2) return stmt->inouts->next
34608     {
34609       3d/compare-eax-and 2/imm32
34610       75/jump-if-!= break/disp8
34611 $get-stmt-operand-from-arg-location:2:
34612       (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
34613       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
34614       eb/jump $get-stmt-operand-from-arg-location:end/disp8
34615     }
34616     # if (l == 3) return stmt->outputs
34617     {
34618       3d/compare-eax-and 3/imm32
34619       75/jump-if-!= break/disp8
34620 $get-stmt-operand-from-arg-location:3:
34621       (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
34622       eb/jump $get-stmt-operand-from-arg-location:end/disp8
34623     }
34624     # abort
34625     e9/jump $get-stmt-operand-from-arg-location:abort/disp32
34626 $get-stmt-operand-from-arg-location:end:
34627     # . restore registers
34628     59/pop-to-ecx
34629     # . epilogue
34630     89/<- %esp 5/r32/ebp
34631     5d/pop-to-ebp
34632     c3/return
34633 
34634 $get-stmt-operand-from-arg-location:abort:
34635     # error("invalid arg-location " eax)
34636     (write-buffered *(ebp+0x10) "invalid arg-location ")
34637     (write-int32-hex-buffered *(ebp+0x10) %eax)
34638     (write-buffered *(ebp+0x10) Newline)
34639     (flush *(ebp+0x10))
34640     (stop *(ebp+0x14) 1)
34641     # never gets here
34642 
34643 emit-subx-r32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
34644     # . prologue
34645     55/push-ebp
34646     89/<- %ebp 4/r32/esp
34647     # . save registers
34648     50/push-eax
34649     51/push-ecx
34650     # if (l == 0) return
34651     81 7/subop/compare *(ebp+0xc) 0/imm32
34652     0f 84/jump-if-= $emit-subx-r32:end/disp32
34653     # var v/eax: (addr stmt-var)
34654     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
34655     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
34656     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
34657 #?     (write-buffered Stderr "looking up ")
34658 #?     (write-buffered Stderr %eax)
34659 #?     (write-buffered Stderr Newline)
34660 #?     (flush Stderr)
34661     (maybe-get Mu-registers %eax 0xc)  # => eax: (addr register-index)
34662     (write-buffered *(ebp+8) Space)
34663     (write-int32-hex-buffered *(ebp+8) *eax)
34664     (write-buffered *(ebp+8) "/r32")
34665 $emit-subx-r32:end:
34666     # . restore registers
34667     59/pop-to-ecx
34668     58/pop-to-eax
34669     # . epilogue
34670     89/<- %esp 5/r32/ebp
34671     5d/pop-to-ebp
34672     c3/return
34673 
34674 emit-subx-x32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
34675     # . prologue
34676     55/push-ebp
34677     89/<- %ebp 4/r32/esp
34678     # . save registers
34679     50/push-eax
34680     51/push-ecx
34681     # if (l == 0) return
34682     81 7/subop/compare *(ebp+0xc) 0/imm32
34683     0f 84/jump-if-= $emit-subx-x32:end/disp32
34684     # var v/eax: (addr stmt-var)
34685     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
34686     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
34687     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
34688 #?     (write-buffered Stderr "looking up ")
34689 #?     (write-buffered Stderr %eax)
34690 #?     (write-buffered Stderr Newline)
34691 #?     (flush Stderr)
34692     (maybe-get Mu-registers %eax 0xc)  # => eax: (addr register-index)
34693     (write-buffered *(ebp+8) Space)
34694     (write-int32-hex-buffered *(ebp+8) *eax)
34695     (write-buffered *(ebp+8) "/x32")
34696 $emit-subx-x32:end:
34697     # . restore registers
34698     59/pop-to-ecx
34699     58/pop-to-eax
34700     # . epilogue
34701     89/<- %esp 5/r32/ebp
34702     5d/pop-to-ebp
34703     c3/return
34704 
34705 emit-subx-imm32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
34706     # . prologue
34707     55/push-ebp
34708     89/<- %ebp 4/r32/esp
34709     # . save registers
34710     50/push-eax
34711     51/push-ecx
34712     # if (l == 0) return
34713     81 7/subop/compare *(ebp+0xc) 0/imm32
34714     0f 84/jump-if-= $emit-subx-imm32:end/disp32
34715     # var v/eax: (handle var)
34716     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
34717     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
34718     (lookup *eax *(eax+4))  # Var-name Var-name => eax
34719     (write-buffered *(ebp+8) Space)
34720     (write-buffered *(ebp+8) %eax)
34721     (write-buffered *(ebp+8) "/imm32")
34722 $emit-subx-imm32:end:
34723     # . restore registers
34724     59/pop-to-ecx
34725     58/pop-to-eax
34726     # . epilogue
34727     89/<- %esp 5/r32/ebp
34728     5d/pop-to-ebp
34729     c3/return
34730 
34731 emit-subx-imm8:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
34732     # . prologue
34733     55/push-ebp
34734     89/<- %ebp 4/r32/esp
34735     # . save registers
34736     50/push-eax
34737     51/push-ecx
34738     # if (l == 0) return
34739     81 7/subop/compare *(ebp+0xc) 0/imm32
34740     0f 84/jump-if-= $emit-subx-imm32:end/disp32
34741     # var v/eax: (handle var)
34742     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
34743     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
34744     (lookup *eax *(eax+4))  # Var-name Var-name => eax
34745     (write-buffered *(ebp+8) Space)
34746     (write-buffered *(ebp+8) %eax)
34747     (write-buffered *(ebp+8) "/imm8")
34748 $emit-subx-imm8:end:
34749     # . restore registers
34750     59/pop-to-ecx
34751     58/pop-to-eax
34752     # . epilogue
34753     89/<- %esp 5/r32/ebp
34754     5d/pop-to-ebp
34755     c3/return
34756 
34757 emit-subx-disp32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
34758     # . prologue
34759     55/push-ebp
34760     89/<- %ebp 4/r32/esp
34761     # . save registers
34762     50/push-eax
34763     51/push-ecx
34764     # if (location == 0) return
34765     81 7/subop/compare *(ebp+0xc) 0/imm32
34766     0f 84/jump-if-= $emit-subx-disp32:end/disp32
34767     # var v/eax: (addr stmt-var)
34768     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # => eax
34769     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
34770     (lookup *eax *(eax+4))  # Var-name Var-name => eax
34771     (write-buffered *(ebp+8) Space)
34772     (write-buffered *(ebp+8) %eax)
34773     # hack: if instruction operation starts with "break", emit ":break"
34774     # var name/ecx: (addr array byte) = lookup(stmt->operation)
34775     8b/-> *(ebp+0x10) 0/r32/eax
34776     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
34777     89/<- %ecx 0/r32/eax
34778     {
34779       (string-starts-with? %ecx "break")  # => eax
34780       3d/compare-eax-and 0/imm32/false
34781       74/jump-if-= break/disp8
34782       (write-buffered *(ebp+8) ":break")
34783     }
34784     # hack: if instruction operation starts with "loop", emit ":loop"
34785     {
34786       (string-starts-with? %ecx "loop")  # => eax
34787       3d/compare-eax-and 0/imm32/false
34788       74/jump-if-= break/disp8
34789       (write-buffered *(ebp+8) ":loop")
34790     }
34791     (write-buffered *(ebp+8) "/disp32")
34792 $emit-subx-disp32:end:
34793     # . restore registers
34794     59/pop-to-ecx
34795     58/pop-to-eax
34796     # . epilogue
34797     89/<- %esp 5/r32/ebp
34798     5d/pop-to-ebp
34799     c3/return
34800 
34801 emit-call:  # out: (addr buffered-file), stmt: (addr stmt)
34802     # . prologue
34803     55/push-ebp
34804     89/<- %ebp 4/r32/esp
34805     # . save registers
34806     50/push-eax
34807     51/push-ecx
34808     #
34809     (emit-indent *(ebp+8) *Curr-block-depth)
34810     (write-buffered *(ebp+8) "(")
34811     # ecx = stmt
34812     8b/-> *(ebp+0xc) 1/r32/ecx
34813     # - emit function name
34814     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
34815     (write-buffered *(ebp+8) %eax)
34816     # - emit arguments
34817     # var curr/eax: (addr stmt-var) = lookup(stmt->inouts)
34818     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
34819     {
34820       # if (curr == null) break
34821       3d/compare-eax-and 0/imm32
34822       74/jump-if-= break/disp8
34823       #
34824       (emit-subx-call-operand *(ebp+8) %eax)
34825       # curr = lookup(curr->next)
34826       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
34827       eb/jump loop/disp8
34828     }
34829     #
34830     (write-buffered *(ebp+8) ")\n")
34831 $emit-call:end:
34832     # . restore registers
34833     59/pop-to-ecx
34834     58/pop-to-eax
34835     # . epilogue
34836     89/<- %esp 5/r32/ebp
34837     5d/pop-to-ebp
34838     c3/return
34839 
34840 emit-subx-call-operand:  # out: (addr buffered-file), s: (addr stmt-var)
34841     # shares code with emit-subx-var-as-rm32
34842     # . prologue
34843     55/push-ebp
34844     89/<- %ebp 4/r32/esp
34845     # . save registers
34846     50/push-eax
34847     51/push-ecx
34848     56/push-esi
34849     # ecx = s
34850     8b/-> *(ebp+0xc) 1/r32/ecx
34851     # var operand/esi: (addr var) = lookup(s->value)
34852     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
34853     89/<- %esi 0/r32/eax
34854     # if (operand->register && !s->is-deref?) emit "%__"
34855     {
34856 $emit-subx-call-operand:check-for-register-direct:
34857       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
34858       74/jump-if-= break/disp8
34859       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
34860       75/jump-if-!= break/disp8
34861 $emit-subx-call-operand:register-direct:
34862       (write-buffered *(ebp+8) " %")
34863       (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
34864       (write-buffered *(ebp+8) %eax)
34865       e9/jump $emit-subx-call-operand:end/disp32
34866     }
34867     # else if (operand->register && s->is-deref?) emit "*__"
34868     {
34869 $emit-subx-call-operand:check-for-register-indirect:
34870       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
34871       74/jump-if-= break/disp8
34872       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
34873       74/jump-if-= break/disp8
34874 $emit-subx-call-operand:register-indirect:
34875       (emit-subx-call-operand-register-indirect *(ebp+8) %esi)
34876       e9/jump $emit-subx-call-operand:end/disp32
34877     }
34878     # else if (operand->stack-offset) emit "*(ebp+__)"
34879     {
34880       81 7/subop/compare *(esi+0x14) 0/imm32  # Var-offset
34881       74/jump-if-= break/disp8
34882 $emit-subx-call-operand:stack:
34883       (emit-subx-call-operand-stack *(ebp+8) %esi)
34884       e9/jump $emit-subx-call-operand:end/disp32
34885     }
34886     # else if (operand->type == literal) emit "__"
34887     {
34888       (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
34889       81 7/subop/compare *(eax+4) 0/imm32  # Type-tree-value
34890       75/jump-if-!= break/disp8
34891 $emit-subx-call-operand:literal:
34892       (write-buffered *(ebp+8) Space)
34893       (lookup *esi *(esi+4))  # Var-name Var-name => eax
34894       (write-buffered *(ebp+8) %eax)
34895       e9/jump $emit-subx-call-operand:end/disp32
34896     }
34897     # else if (operand->type == literal-string) emit "__"
34898     {
34899       (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
34900       81 7/subop/compare *(eax+4) 0x10/imm32  # Type-tree-value
34901       75/jump-if-!= break/disp8
34902 $emit-subx-call-operand:literal-string:
34903       (write-buffered *(ebp+8) Space)
34904       (lookup *esi *(esi+4))  # Var-name Var-name => eax
34905       (write-buffered *(ebp+8) %eax)
34906     }
34907 $emit-subx-call-operand:end:
34908     # . restore registers
34909     5e/pop-to-esi
34910     59/pop-to-ecx
34911     58/pop-to-eax
34912     # . epilogue
34913     89/<- %esp 5/r32/ebp
34914     5d/pop-to-ebp
34915     c3/return
34916 
34917 emit-subx-call-operand-register-indirect:  # out: (addr buffered-file), v: (addr var)
34918     # . prologue
34919     55/push-ebp
34920     89/<- %ebp 4/r32/esp
34921     # . save registers
34922     50/push-eax
34923     51/push-ecx
34924     56/push-esi
34925     # esi = v
34926     8b/-> *(ebp+0xc) 6/r32/esi
34927     # var size/ecx: int = size-of-deref(v)
34928     (size-of-deref %esi)  # => eax
34929     89/<- %ecx 0/r32/eax
34930     # var reg-name/esi: (addr array byte) = lookup(v->register)
34931     (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
34932     89/<- %esi 0/r32/eax
34933     # TODO: assert size is a multiple of 4
34934     # var i/eax: int = 0
34935     b8/copy-to-eax 0/imm32
34936     {
34937 $emit-subx-call-operand-register-indirect:loop:
34938       # if (i >= size) break
34939       39/compare %eax 1/r32/ecx
34940       7d/jump-if->= break/disp8
34941       # emit " *(" v->register "+" i ")"
34942       (write-buffered *(ebp+8) " *(")
34943       (write-buffered *(ebp+8) %esi)
34944       (write-buffered *(ebp+8) "+")
34945       (write-int32-hex-buffered *(ebp+8) %eax)
34946       (write-buffered *(ebp+8) ")")
34947       # i += 4
34948       05/add-to-eax 4/imm32
34949       #
34950       eb/jump loop/disp8
34951     }
34952 $emit-subx-call-operand-register-indirect:end:
34953     # . restore registers
34954     5e/pop-to-esi
34955     59/pop-to-ecx
34956     58/pop-to-eax
34957     # . epilogue
34958     89/<- %esp 5/r32/ebp
34959     5d/pop-to-ebp
34960     c3/return
34961 
34962 emit-subx-call-operand-stack:  # out: (addr buffered-file), v: (addr var)
34963     # . prologue
34964     55/push-ebp
34965     89/<- %ebp 4/r32/esp
34966     # . save registers
34967     50/push-eax
34968     51/push-ecx
34969     56/push-esi
34970     # esi = v
34971     8b/-> *(ebp+0xc) 6/r32/esi
34972     # var curr/ecx: int = v->offset
34973     8b/-> *(esi+0x14) 1/r32/ecx  # Var-offset
34974     # var max/eax: int = v->offset + size-of(v)
34975     (size-of %esi)  # => eax
34976     # TODO: assert size is a multiple of 4
34977     01/add-to %eax 1/r32/ecx
34978     {
34979 $emit-subx-call-operand-stack:loop:
34980       # if (curr >= max) break
34981       39/compare %ecx 0/r32/eax
34982       7d/jump-if->= break/disp8
34983       # emit " *(ebp+" curr ")"
34984       (write-buffered *(ebp+8) " *(ebp+")
34985       (write-int32-hex-buffered *(ebp+8) %ecx)
34986       (write-buffered *(ebp+8) ")")
34987       # i += 4
34988       81 0/subop/add %ecx 4/imm32
34989       #
34990       eb/jump loop/disp8
34991     }
34992 $emit-subx-call-operand-stack:end:
34993     # . restore registers
34994     5e/pop-to-esi
34995     59/pop-to-ecx
34996     58/pop-to-eax
34997     # . epilogue
34998     89/<- %esp 5/r32/ebp
34999     5d/pop-to-ebp
35000     c3/return
35001 
35002 emit-subx-var-as-rm32:  # out: (addr buffered-file), s: (addr stmt-var)
35003     # . prologue
35004     55/push-ebp
35005     89/<- %ebp 4/r32/esp
35006     # . save registers
35007     50/push-eax
35008     51/push-ecx
35009     56/push-esi
35010     # ecx = s
35011     8b/-> *(ebp+0xc) 1/r32/ecx
35012     # var operand/esi: (addr var) = lookup(s->value)
35013     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
35014     89/<- %esi 0/r32/eax
35015     # if (operand->register && s->is-deref?) emit "*__"
35016     {
35017 $emit-subx-var-as-rm32:check-for-register-indirect:
35018       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
35019       74/jump-if-= break/disp8
35020       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
35021       74/jump-if-= break/disp8
35022 $emit-subx-var-as-rm32:register-indirect:
35023       (write-buffered *(ebp+8) " *")
35024       (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
35025       (write-buffered *(ebp+8) %eax)
35026       e9/jump $emit-subx-var-as-rm32:end/disp32
35027     }
35028     # if (operand->register && !s->is-deref?) emit "%__"
35029     {
35030 $emit-subx-var-as-rm32:check-for-register-direct:
35031       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
35032       74/jump-if-= break/disp8
35033       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
35034       75/jump-if-!= break/disp8
35035 $emit-subx-var-as-rm32:register-direct:
35036       (write-buffered *(ebp+8) " %")
35037       (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
35038       (write-buffered *(ebp+8) %eax)
35039       e9/jump $emit-subx-var-as-rm32:end/disp32
35040     }
35041     # else if (operand->stack-offset) emit "*(ebp+__)"
35042     {
35043       81 7/subop/compare *(esi+0x14) 0/imm32  # Var-offset
35044       74/jump-if-= break/disp8
35045 $emit-subx-var-as-rm32:stack:
35046       (write-buffered *(ebp+8) Space)
35047       (write-buffered *(ebp+8) "*(ebp+")
35048       (write-int32-hex-buffered *(ebp+8) *(esi+0x14))  # Var-offset
35049       (write-buffered *(ebp+8) ")")
35050     }
35051 $emit-subx-var-as-rm32:end:
35052     # . restore registers
35053     5e/pop-to-esi
35054     59/pop-to-ecx
35055     58/pop-to-eax
35056     # . epilogue
35057     89/<- %esp 5/r32/ebp
35058     5d/pop-to-ebp
35059     c3/return
35060 
35061 find-matching-primitive:  # primitives: (addr primitive), stmt: (addr stmt) -> result/eax: (addr primitive)
35062     # . prologue
35063     55/push-ebp
35064     89/<- %ebp 4/r32/esp
35065     # . save registers
35066     51/push-ecx
35067     # var curr/ecx: (addr primitive) = primitives
35068     8b/-> *(ebp+8) 1/r32/ecx
35069     {
35070 $find-matching-primitive:loop:
35071       # if (curr == null) break
35072       81 7/subop/compare %ecx 0/imm32
35073       74/jump-if-= break/disp8
35074       # if match(curr, stmt) return curr
35075       {
35076         (mu-stmt-matches-primitive? *(ebp+0xc) %ecx)  # => eax
35077         3d/compare-eax-and 0/imm32/false
35078         74/jump-if-= break/disp8
35079         89/<- %eax 1/r32/ecx
35080         eb/jump $find-matching-primitive:end/disp8
35081       }
35082 $find-matching-primitive:next-primitive:
35083       # curr = curr->next
35084       (lookup *(ecx+0x3c) *(ecx+0x40))  # Primitive-next Primitive-next => eax
35085       89/<- %ecx 0/r32/eax
35086       #
35087       e9/jump loop/disp32
35088     }
35089     # return null
35090     b8/copy-to-eax 0/imm32
35091 $find-matching-primitive:end:
35092     # . restore registers
35093     59/pop-to-ecx
35094     # . epilogue
35095     89/<- %esp 5/r32/ebp
35096     5d/pop-to-ebp
35097     c3/return
35098 
35099 mu-stmt-matches-primitive?:  # stmt: (addr stmt), primitive: (addr primitive) -> result/eax: boolean
35100     # A mu stmt matches a primitive if the name matches, all the inout vars
35101     # match, and all the output vars match.
35102     # Vars match if types match and registers match.
35103     # In addition, a stmt output matches a primitive's output if types match
35104     # and the primitive has a wildcard register.
35105     # . prologue
35106     55/push-ebp
35107     89/<- %ebp 4/r32/esp
35108     # . save registers
35109     51/push-ecx
35110     52/push-edx
35111     53/push-ebx
35112     56/push-esi
35113     57/push-edi
35114     # ecx = stmt
35115     8b/-> *(ebp+8) 1/r32/ecx
35116     # edx = primitive
35117     8b/-> *(ebp+0xc) 2/r32/edx
35118     {
35119 $mu-stmt-matches-primitive?:check-name:
35120       # if (primitive->name != stmt->operation) return false
35121       # . var esi: (addr array byte) = lookup(stmt->operation)
35122       (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
35123       89/<- %esi 0/r32/eax
35124       # . var edi: (addr array byte) = lookup(primitive->name)
35125       (lookup *edx *(edx+4))  # Primitive-name Primitive-name => eax
35126 #?       (write-buffered Stderr %eax)
35127 #?       (write-buffered Stderr Newline)
35128 #?       (flush Stderr)
35129       89/<- %edi 0/r32/eax
35130       (string-equal? %esi %edi)  # => eax
35131       3d/compare-eax-and 0/imm32/false
35132       75/jump-if-!= break/disp8
35133       b8/copy-to-eax 0/imm32
35134       e9/jump $mu-stmt-matches-primitive?:end/disp32
35135     }
35136     # var curr/esi: (addr stmt-var) = lookup(stmt->inouts)
35137     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
35138     89/<- %esi 0/r32/eax
35139     # var curr2/edi: (addr list var) = lookup(primitive->inouts)
35140     (lookup *(edx+8) *(edx+0xc))  # Primitive-inouts Primitive-inouts => eax
35141     89/<- %edi 0/r32/eax
35142     {
35143 $mu-stmt-matches-primitive?:inouts-loop:
35144       # if (curr == 0 && curr2 == 0) move on to check outputs
35145       {
35146 $mu-stmt-matches-primitive?:check-both-inouts-null:
35147         81 7/subop/compare %esi 0/imm32
35148         75/jump-if-!= break/disp8
35149 $mu-stmt-matches-primitive?:stmt-inout-null:
35150         81 7/subop/compare %edi 0/imm32
35151         0f 84/jump-if-= $mu-stmt-matches-primitive?:check-outputs/disp32
35152 $mu-stmt-matches-primitive?:stmt-inout-null-and-prim-inout-not-null:
35153         # return false
35154         b8/copy-to-eax 0/imm32/false
35155         e9/jump $mu-stmt-matches-primitive?:end/disp32
35156       }
35157       # if (curr2 == 0) return false
35158       {
35159 $mu-stmt-matches-primitive?:check-prim-inout-null:
35160         81 7/subop/compare %edi 0/imm32
35161         75/jump-if-!= break/disp8
35162 $mu-stmt-matches-primitive?:prim-inout-null:
35163         b8/copy-to-eax 0/imm32/false
35164         e9/jump $mu-stmt-matches-primitive?:end/disp32
35165       }
35166       # if (curr != curr2) return false
35167       {
35168 $mu-stmt-matches-primitive?:check-inouts-match:
35169         (lookup *edi *(edi+4))  # List-value List-value => eax
35170         (operand-matches-primitive? %esi %eax)  # => eax
35171         3d/compare-eax-and 0/imm32/false
35172         75/jump-if-!= break/disp8
35173 $mu-stmt-matches-primitive?:inouts-match:
35174         b8/copy-to-eax 0/imm32/false
35175         e9/jump $mu-stmt-matches-primitive?:end/disp32
35176       }
35177 $mu-stmt-matches-primitive?:next-inout:
35178       # curr = lookup(curr->next)
35179       (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
35180       89/<- %esi 0/r32/eax
35181       # curr2 = lookup(curr2->next)
35182       (lookup *(edi+8) *(edi+0xc))  # List-next List-next => eax
35183       89/<- %edi 0/r32/eax
35184       #
35185       e9/jump loop/disp32
35186     }
35187 $mu-stmt-matches-primitive?:check-outputs:
35188     # var curr/esi: (addr stmt-var) = lookup(stmt->outputs)
35189     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
35190     89/<- %esi 0/r32/eax
35191     # var curr2/edi: (addr list var) = lookup(primitive->outputs)
35192     (lookup *(edx+0x10) *(edx+0x14))  # Primitive-outputs Primitive-outputs => eax
35193     89/<- %edi 0/r32/eax
35194     {
35195 $mu-stmt-matches-primitive?:outputs-loop:
35196       # if (curr == 0) return (curr2 == 0)
35197       {
35198 $mu-stmt-matches-primitive?:check-both-outputs-null:
35199         81 7/subop/compare %esi 0/imm32
35200         75/jump-if-!= break/disp8
35201         {
35202 $mu-stmt-matches-primitive?:stmt-output-null:
35203           81 7/subop/compare %edi 0/imm32
35204           75/jump-if-!= break/disp8
35205 $mu-stmt-matches-primitive?:both-outputs-null:
35206           # return true
35207           b8/copy-to-eax 1/imm32
35208           e9/jump $mu-stmt-matches-primitive?:end/disp32
35209         }
35210 $mu-stmt-matches-primitive?:stmt-output-null-and-prim-output-not-null:
35211         # return false
35212         b8/copy-to-eax 0/imm32
35213         e9/jump $mu-stmt-matches-primitive?:end/disp32
35214       }
35215       # if (curr2 == 0) return false
35216       {
35217 $mu-stmt-matches-primitive?:check-prim-output-null:
35218         81 7/subop/compare %edi 0/imm32
35219         75/jump-if-!= break/disp8
35220 $mu-stmt-matches-primitive?:prim-output-is-null:
35221         b8/copy-to-eax 0/imm32
35222         e9/jump $mu-stmt-matches-primitive?:end/disp32
35223       }
35224       # if (curr != curr2) return false
35225       {
35226 $mu-stmt-matches-primitive?:check-outputs-match:
35227         (lookup *edi *(edi+4))  # List-value List-value => eax
35228         (operand-matches-primitive? %esi %eax)  # => eax
35229         3d/compare-eax-and 0/imm32/false
35230         75/jump-if-!= break/disp8
35231 $mu-stmt-matches-primitive?:outputs-match:
35232         b8/copy-to-eax 0/imm32
35233         e9/jump $mu-stmt-matches-primitive?:end/disp32
35234       }
35235 $mu-stmt-matches-primitive?:next-output:
35236       # curr = lookup(curr->next)
35237       (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
35238       89/<- %esi 0/r32/eax
35239       # curr2 = lookup(curr2->next)
35240       (lookup *(edi+8) *(edi+0xc))  # List-next List-next => eax
35241       89/<- %edi 0/r32/eax
35242       #
35243       e9/jump loop/disp32
35244     }
35245 $mu-stmt-matches-primitive?:return-true:
35246     b8/copy-to-eax 1/imm32
35247 $mu-stmt-matches-primitive?:end:
35248     # . restore registers
35249     5f/pop-to-edi
35250     5e/pop-to-esi
35251     5b/pop-to-ebx
35252     5a/pop-to-edx
35253     59/pop-to-ecx
35254     # . epilogue
35255     89/<- %esp 5/r32/ebp
35256     5d/pop-to-ebp
35257     c3/return
35258 
35259 operand-matches-primitive?:  # s: (addr stmt-var), prim-var: (addr var) -> result/eax: boolean
35260     # . prologue
35261     55/push-ebp
35262     89/<- %ebp 4/r32/esp
35263     # . save registers
35264     51/push-ecx
35265     52/push-edx
35266     53/push-ebx
35267     56/push-esi
35268     57/push-edi
35269     # ecx = s
35270     8b/-> *(ebp+8) 1/r32/ecx
35271     # var var/esi: (addr var) = lookup(s->value)
35272     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
35273     89/<- %esi 0/r32/eax
35274     # edi = prim-var
35275     8b/-> *(ebp+0xc) 7/r32/edi
35276 $operand-matches-primitive?:check-type:
35277     # if !category-match?(var->type, prim-var->type) return false
35278     # . var vtype/ebx: (addr type-tree) = lookup(var->type)
35279     (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
35280     89/<- %ebx 0/r32/eax
35281     # . if s is deref, vtype = vtype->right
35282     {
35283       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
35284       74/jump-if-= break/disp8
35285 $operand-matches-primitive?:is-deref:
35286       # . var t/eax: (addr type)
35287       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
35288       # . if !t->is-atom? t = t->left
35289       81 7/subop/compare *eax 0/imm32/false
35290       {
35291         75/jump-if-!= break/disp8
35292         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
35293       }
35294       # .
35295       89/<- %ebx 0/r32/eax
35296     }
35297     # . var ptype/eax: (addr type-tree) = lookup(prim-var->type)
35298     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
35299     (subx-type-category-match? %ebx %eax)  # => eax
35300     3d/compare-eax-and 0/imm32/false
35301     0f 84/jump-if-= $operand-matches-primitive?:return-false/disp32
35302     {
35303 $operand-matches-primitive?:check-register:
35304       # if prim-var is in memory and var is in register but dereference, match
35305       {
35306         81 7/subop/compare *(edi+0x18) 0/imm32  # Var-register
35307         0f 85/jump-if-!= break/disp32
35308         81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
35309         74/jump-if-= break/disp8
35310         81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
35311         74/jump-if-= break/disp8
35312 $operand-matches-primitive?:var-deref-match:
35313         e9/jump $operand-matches-primitive?:return-true/disp32
35314       }
35315       # if prim-var is in register and var is in register but dereference, no match
35316       {
35317         81 7/subop/compare *(edi+0x18) 0/imm32  # Var-register
35318         0f 84/jump-if-= break/disp32
35319         81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
35320         0f 84/jump-if-= break/disp32
35321         81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
35322         74/jump-if-= break/disp8
35323 $operand-matches-primitive?:var-deref-no-match:
35324         e9/jump $operand-matches-primitive?:return-false/disp32
35325       }
35326       # return false if var->register doesn't match prim-var->register
35327       {
35328         # if register addresses are equal, it's a match
35329         # var vreg/ebx: (addr array byte) = lookup(var->register)
35330         (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
35331         89/<- %ebx 0/r32/eax
35332         # var preg/ecx: (addr array byte) = lookup(prim-var->register)
35333         (lookup *(edi+0x18) *(edi+0x1c))  # Var-register Var-register => eax
35334         89/<- %ecx 0/r32/eax
35335         # if (vreg == preg) break
35336         39/compare %ecx 3/r32/ebx
35337         74/jump-if-= break/disp8
35338 $operand-matches-primitive?:var-register-no-match:
35339         # if either address is 0, return false
35340         81 7/subop/compare %ebx 0/imm32
35341         74/jump-if-=  $operand-matches-primitive?:return-false/disp8
35342         81 7/subop/compare %ecx 0/imm32
35343         74/jump-if-=  $operand-matches-primitive?:return-false/disp8
35344         # if prim-var->register is wildcard, it's a match
35345         (string-equal? %ecx "*")  # Any-register => eax
35346         3d/compare-eax-and 0/imm32/false
35347         75/jump-if-!= break/disp8
35348 $operand-matches-primitive?:wildcard-no-match:
35349         # if string contents aren't equal, return false
35350         (string-equal? %ecx %ebx)  # => eax
35351         3d/compare-eax-and 0/imm32/false
35352         74/jump-if-= $operand-matches-primitive?:return-false/disp8
35353       }
35354     }
35355 $operand-matches-primitive?:return-true:
35356     b8/copy-to-eax 1/imm32/true
35357     eb/jump $operand-matches-primitive?:end/disp8
35358 $operand-matches-primitive?:return-false:
35359     b8/copy-to-eax 0/imm32/false
35360 $operand-matches-primitive?:end:
35361     # . restore registers
35362     5f/pop-to-edi
35363     5e/pop-to-esi
35364     5b/pop-to-ebx
35365     5a/pop-to-edx
35366     59/pop-to-ecx
35367     # . epilogue
35368     89/<- %esp 5/r32/ebp
35369     5d/pop-to-ebp
35370     c3/return
35371 
35372 find-matching-function:  # functions: (addr function), stmt: (addr stmt) -> result/eax: (addr function)
35373     # . prologue
35374     55/push-ebp
35375     89/<- %ebp 4/r32/esp
35376     # . save registers
35377     51/push-ecx
35378     # var curr/ecx: (handle function) = functions
35379     8b/-> *(ebp+8) 1/r32/ecx
35380     {
35381       # if (curr == null) break
35382       81 7/subop/compare %ecx 0/imm32
35383       74/jump-if-= break/disp8
35384 #?       (write-buffered Stderr "iter\n")
35385 #?       (flush Stderr)
35386       # if match(stmt, curr) return curr
35387       {
35388         (mu-stmt-matches-function? *(ebp+0xc) %ecx)  # => eax
35389         3d/compare-eax-and 0/imm32/false
35390         74/jump-if-= break/disp8
35391         89/<- %eax 1/r32/ecx
35392         eb/jump $find-matching-function:end/disp8
35393       }
35394       # curr = curr->next
35395       (lookup *(ecx+0x20) *(ecx+0x24))  # Function-next Function-next => eax
35396       89/<- %ecx 0/r32/eax
35397       #
35398       eb/jump loop/disp8
35399     }
35400     # return null
35401     b8/copy-to-eax 0/imm32
35402 $find-matching-function:end:
35403     # . restore registers
35404     59/pop-to-ecx
35405     # . epilogue
35406     89/<- %esp 5/r32/ebp
35407     5d/pop-to-ebp
35408     c3/return
35409 
35410 # Just compare names; user-defined functions don't support overloading yet.
35411 mu-stmt-matches-function?:  # stmt: (addr stmt1), function: (addr function) -> result/eax: boolean
35412     # . prologue
35413     55/push-ebp
35414     89/<- %ebp 4/r32/esp
35415     # . save registers
35416     51/push-ecx
35417     # return function->name == stmt->operation
35418     # ecx = lookup(stmt->operation)
35419     8b/-> *(ebp+8) 0/r32/eax
35420     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
35421     89/<- %ecx 0/r32/eax
35422     # eax = lookup(function->name)
35423     8b/-> *(ebp+0xc) 0/r32/eax
35424     (lookup *eax *(eax+4))  # Function-name Function-name => eax
35425     (string-equal? %eax %ecx)  # => eax
35426 $mu-stmt-matches-function?:end:
35427     # . restore registers
35428     59/pop-to-ecx
35429     # . epilogue
35430     89/<- %esp 5/r32/ebp
35431     5d/pop-to-ebp
35432     c3/return
35433 
35434 # Type-checking happens elsewhere. This method is for selecting between
35435 # primitives.
35436 subx-type-category-match?:  # a: (addr type-tree), b: (addr type-tree) -> result/eax: boolean
35437     # . prologue
35438     55/push-ebp
35439     89/<- %ebp 4/r32/esp
35440     # . save registers
35441     51/push-ecx
35442     # var cata/ecx: int = type-category(a)
35443     (type-category *(ebp+8))  # => eax
35444     89/<- %ecx 0/r32/eax
35445     # var catb/eax: int = type-category(b)
35446     (type-category *(ebp+0xc))  # => eax
35447     # return cata == catb
35448     39/compare %eax 1/r32/ecx
35449     0f 94/set-byte-if-= %al
35450     81 4/subop/and %eax 0xff/imm32
35451 $subx-type-category-match?:end:
35452     # . restore registers
35453     59/pop-to-ecx
35454     # . epilogue
35455     89/<- %esp 5/r32/ebp
35456     5d/pop-to-ebp
35457     c3/return
35458 
35459 type-category:  # a: (addr type-tree) -> result/eax: int
35460     # . prologue
35461     55/push-ebp
35462     89/<- %ebp 4/r32/esp
35463     # . save registers
35464     51/push-ecx
35465     # var lit?/ecx: boolean = is-literal-type?(a)
35466     (is-simple-mu-type? *(ebp+8) 0)  # literal => eax
35467     89/<- %ecx 0/r32/eax
35468     # var float?/eax: int = is-float?(a)
35469     (is-simple-mu-type? *(ebp+8) 0xf)  # => eax
35470     # set bits for lit? and float?
35471     c1/shift 4/subop/left %ecx 1/imm8
35472     09/or %eax 1/r32/ecx
35473 $type-category:end:
35474     # . restore registers
35475     59/pop-to-ecx
35476     # . epilogue
35477     89/<- %esp 5/r32/ebp
35478     5d/pop-to-ebp
35479     c3/return
35480 
35481 is-simple-mu-type?:  # a: (addr type-tree), n: type-id -> result/eax: boolean
35482     # . prologue
35483     55/push-ebp
35484     89/<- %ebp 4/r32/esp
35485     # . save registers
35486     51/push-ecx
35487     # ecx = n
35488     8b/-> *(ebp+0xc) 1/r32/ecx
35489     # return (a->value == n)
35490     8b/-> *(ebp+8) 0/r32/eax
35491     39/compare *(eax+4) 1/r32/ecx  # Type-tree-value
35492     0f 94/set-byte-if-= %al
35493     81 4/subop/and %eax 0xff/imm32
35494 $is-simple-mu-type?:end:
35495     # . restore registers
35496     59/pop-to-ecx
35497     # . epilogue
35498     89/<- %esp 5/r32/ebp
35499     5d/pop-to-ebp
35500     c3/return
35501 
35502 is-mu-addr-type?:  # a: (addr type-tree) -> result/eax: boolean
35503     # . prologue
35504     55/push-ebp
35505     89/<- %ebp 4/r32/esp
35506     # eax = a
35507     8b/-> *(ebp+8) 0/r32/eax
35508     # if (!a->is-atom?) a = a->left
35509     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
35510     {
35511       75/jump-if-!= break/disp8
35512       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
35513     }
35514     # return (a->value == addr)
35515     81 7/subop/compare *(eax+4) 2/imm32/addr  # Type-tree-value
35516     0f 94/set-byte-if-= %al
35517     81 4/subop/and %eax 0xff/imm32
35518 $is-mu-addr-type?:end:
35519     # . epilogue
35520     89/<- %esp 5/r32/ebp
35521     5d/pop-to-ebp
35522     c3/return
35523 
35524 is-mu-array-type?:  # a: (addr type-tree) -> result/eax: boolean
35525     # . prologue
35526     55/push-ebp
35527     89/<- %ebp 4/r32/esp
35528     # eax = a
35529     8b/-> *(ebp+8) 0/r32/eax
35530     # if (!a->is-atom?) a = a->left
35531     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
35532     {
35533       75/jump-if-!= break/disp8
35534       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
35535     }
35536     # return (a->value == array)
35537     81 7/subop/compare *(eax+4) 3/imm32/array  # Type-tree-value
35538     0f 94/set-byte-if-= %al
35539     81 4/subop/and %eax 0xff/imm32
35540 $is-mu-array-type?:end:
35541     # . epilogue
35542     89/<- %esp 5/r32/ebp
35543     5d/pop-to-ebp
35544     c3/return
35545 
35546 is-mu-string-type?:  # a: (addr type-tree) -> result/eax: boolean
35547     # . prologue
35548     55/push-ebp
35549     89/<- %ebp 4/r32/esp
35550     # . save registers
35551     56/push-esi
35552     # esi = a
35553     8b/-> *(ebp+8) 6/r32/esi
35554     # if (a->is-atom?) return false
35555     81 7/subop/compare *esi 0/imm32/false  # Type-tree-is-atom
35556     0f 85/jump-if-!= $is-mu-string-type?:return-false/disp32
35557     # if a is not an addr, return false
35558     (is-mu-addr-type? %esi)  # => eax
35559     3d/compare-eax-with 0/imm32/false
35560     0f 84/jump-if-= $is-mu-string-type?:end/disp32  # eax changes var
35561     # if a is not an array, return false
35562     (lookup *(esi+0xc) *(esi+0x10))  # Type-tree-right Type-tree-right => eax
35563     (is-mu-array-type? %eax)  # => eax
35564     3d/compare-eax-with 0/imm32/false
35565     74/jump-if-= $is-mu-string-type?:end/disp8  # eax changes var
35566     # var p/eax: (addr type-tree) = payload of a
35567     (lookup *(esi+0xc) *(esi+0x10))  # Type-tree-right Type-tree-right => eax
35568     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
35569     # if p is an atom, return false
35570     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
35571     75/jump-if-!= $is-mu-string-type?:return-false/disp8
35572     # return (p == byte)
35573     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
35574     (is-simple-mu-type? %eax 8)  # byte => eax
35575     eb/jump $is-mu-string-type?:end/disp8
35576 $is-mu-string-type?:return-false:
35577     b8/copy-to-eax 0/imm32/false
35578 $is-mu-string-type?:end:
35579     # . restore registers
35580     5e/pop-to-esi
35581     # . epilogue
35582     89/<- %esp 5/r32/ebp
35583     5d/pop-to-ebp
35584     c3/return
35585 
35586 is-mu-stream-type?:  # a: (addr type-tree) -> result/eax: boolean
35587     # . prologue
35588     55/push-ebp
35589     89/<- %ebp 4/r32/esp
35590     # eax = a
35591     8b/-> *(ebp+8) 0/r32/eax
35592     # if (!a->is-atom?) a = a->left
35593     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
35594     {
35595       75/jump-if-!= break/disp8
35596       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
35597     }
35598     # return (a->value == stream)
35599     81 7/subop/compare *(eax+4) 0xb/imm32/stream  # Type-tree-value
35600     0f 94/set-byte-if-= %al
35601     81 4/subop/and %eax 0xff/imm32
35602 $is-mu-stream-type?:end:
35603     # . epilogue
35604     89/<- %esp 5/r32/ebp
35605     5d/pop-to-ebp
35606     c3/return
35607 
35608 test-emit-subx-stmt-primitive:
35609     # Primitive operation on a variable on the stack.
35610     #   increment foo
35611     # =>
35612     #   ff 0/subop/increment *(ebp-8)
35613     #
35614     # There's a variable on the var stack as follows:
35615     #   name: 'foo'
35616     #   type: int
35617     #   stack-offset: -8
35618     #
35619     # There's a primitive with this info:
35620     #   name: 'increment'
35621     #   inouts: int/mem
35622     #   value: 'ff 0/subop/increment'
35623     #
35624     # . prologue
35625     55/push-ebp
35626     89/<- %ebp 4/r32/esp
35627     # setup
35628     (clear-stream _test-output-stream)
35629     (clear-stream $_test-output-buffered-file->buffer)
35630     # simulate allocated payloads starting with an initial fake alloc-id (0x11)
35631 $test-emit-subx-stmt-primitive:initialize-type:
35632     # var type/ecx: (payload type-tree) = int
35633     68/push 0/imm32/right:null
35634     68/push 0/imm32/right:null
35635     68/push 0/imm32/left:unused
35636     68/push 1/imm32/value:int
35637     68/push 1/imm32/is-atom?:true
35638     68/push 0x11/imm32/alloc-id:fake:payload
35639     89/<- %ecx 4/r32/esp
35640 $test-emit-subx-stmt-primitive:initialize-var:
35641     # var var-foo/ecx: (payload var) = var(type)
35642     68/push 0/imm32/no-register
35643     68/push 0/imm32/no-register
35644     68/push -8/imm32/stack-offset
35645     68/push 1/imm32/block-depth
35646     51/push-ecx/type
35647     68/push 0x11/imm32/alloc-id:fake
35648     68/push 0/imm32/name
35649     68/push 0/imm32/name
35650     68/push 0x11/imm32/alloc-id:fake:payload
35651     89/<- %ecx 4/r32/esp
35652 $test-emit-subx-stmt-primitive:initialize-var-name:
35653     # var-foo->name = "foo"
35654     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
35655     (copy-array Heap "foo" %eax)
35656 $test-emit-subx-stmt-primitive:initialize-stmt-var:
35657     # var operand/ebx: (payload stmt-var) = stmt-var(var-foo)
35658     68/push 0/imm32/is-deref:false
35659     68/push 0/imm32/next
35660     68/push 0/imm32/next
35661     51/push-ecx/var-foo
35662     68/push 0x11/imm32/alloc-id:fake
35663     68/push 0x11/imm32/alloc-id:fake:payload
35664     89/<- %ebx 4/r32/esp
35665 $test-emit-subx-stmt-primitive:initialize-stmt:
35666     # var stmt/esi: (addr statement)
35667     68/push 0/imm32/no-outputs
35668     68/push 0/imm32/no-outputs
35669     53/push-ebx/inouts
35670     68/push 0x11/imm32/alloc-id:fake
35671     68/push 0/imm32/operation
35672     68/push 0/imm32/operation
35673     68/push 1/imm32/tag
35674     89/<- %esi 4/r32/esp
35675 $test-emit-subx-stmt-primitive:initialize-stmt-operation:
35676     # stmt->operation = "increment"
35677     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
35678     (copy-array Heap "increment" %eax)
35679 $test-emit-subx-stmt-primitive:initialize-primitive:
35680     # var primitives/ebx: (addr primitive)
35681     68/push 0/imm32/next
35682     68/push 0/imm32/next
35683     68/push 0/imm32/no-x32
35684     68/push 0/imm32/no-xm32
35685     68/push 0/imm32/no-disp32
35686     68/push 0/imm32/no-imm8
35687     68/push 0/imm32/no-imm32
35688     68/push 0/imm32/no-r32
35689     68/push 1/imm32/rm32-is-first-inout
35690     68/push 0/imm32/subx-name
35691     68/push 0/imm32/subx-name
35692     68/push 0/imm32/no-outputs
35693     68/push 0/imm32/no-outputs
35694     53/push-ebx/inouts  # hack: reuse stmt-var from call stmt as (list var) in function declaration
35695     68/push 0x11/imm32/alloc-id:fake
35696     68/push 0/imm32/name
35697     68/push 0/imm32/name
35698     89/<- %ebx 4/r32/esp
35699 $test-emit-subx-stmt-primitive:initialize-primitive-name:
35700     # primitives->name = "increment"
35701     (copy-array Heap "increment" %ebx)  # Primitive-name
35702 $test-emit-subx-stmt-primitive:initialize-primitive-subx-name:
35703     # primitives->subx-name = "ff 0/subop/increment"
35704     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
35705     (copy-array Heap "ff 0/subop/increment" %eax)
35706     # convert
35707     c7 0/subop/copy *Curr-block-depth 0/imm32
35708     (emit-subx-stmt _test-output-buffered-file %esi %ebx 0 Stderr 0)
35709     (flush _test-output-buffered-file)
35710 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
35716     # check output
35717     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment *(ebp+0xfffffff8)" "F - test-emit-subx-stmt-primitive")
35718     # . epilogue
35719     89/<- %esp 5/r32/ebp
35720     5d/pop-to-ebp
35721     c3/return
35722 
35723 test-emit-subx-stmt-primitive-register:
35724     # Primitive operation on a variable in a register.
35725     #   foo <- increment
35726     # =>
35727     #   ff 0/subop/increment %eax  # sub-optimal, but should suffice
35728     #
35729     # There's a variable on the var stack as follows:
35730     #   name: 'foo'
35731     #   type: int
35732     #   register: 'eax'
35733     #
35734     # There's a primitive with this info:
35735     #   name: 'increment'
35736     #   out: int/reg
35737     #   value: 'ff 0/subop/increment'
35738     #
35739     # . prologue
35740     55/push-ebp
35741     89/<- %ebp 4/r32/esp
35742     # setup
35743     (clear-stream _test-output-stream)
35744     (clear-stream $_test-output-buffered-file->buffer)
35745 $test-emit-subx-stmt-primitive-register:initialize-type:
35746     # var type/ecx: (payload type-tree) = int
35747     68/push 0/imm32/right:null
35748     68/push 0/imm32/right:null
35749     68/push 0/imm32/left:unused
35750     68/push 1/imm32/value:int
35751     68/push 1/imm32/is-atom?:true
35752     68/push 0x11/imm32/alloc-id:fake:payload
35753     89/<- %ecx 4/r32/esp
35754 $test-emit-subx-stmt-primitive-register:initialize-var:
35755     # var var-foo/ecx: (payload var)
35756     68/push 0/imm32/register
35757     68/push 0/imm32/register
35758     68/push 0/imm32/no-stack-offset
35759     68/push 1/imm32/block-depth
35760     51/push-ecx
35761     68/push 0x11/imm32/alloc-id:fake
35762     68/push 0/imm32/name
35763     68/push 0/imm32/name
35764     68/push 0x11/imm32/alloc-id:fake:payload
35765     89/<- %ecx 4/r32/esp
35766 $test-emit-subx-stmt-primitive-register:initialize-var-name:
35767     # var-foo->name = "foo"
35768     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
35769     (copy-array Heap "foo" %eax)
35770 $test-emit-subx-stmt-primitive-register:initialize-var-register:
35771     # var-foo->register = "eax"
35772     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
35773     (copy-array Heap "eax" %eax)
35774 $test-emit-subx-stmt-primitive-register:initialize-stmt-var:
35775     # var operand/ebx: (payload stmt-var)
35776     68/push 0/imm32/is-deref:false
35777     68/push 0/imm32/next
35778     68/push 0/imm32/next
35779     51/push-ecx/var-foo
35780     68/push 0x11/imm32/alloc-id:fake
35781     68/push 0x11/imm32/alloc-id:fake:payload
35782     89/<- %ebx 4/r32/esp
35783 $test-emit-subx-stmt-primitive-register:initialize-stmt:
35784     # var stmt/esi: (addr statement)
35785     53/push-ebx/outputs
35786     68/push 0x11/imm32/alloc-id:fake
35787     68/push 0/imm32/no-inouts
35788     68/push 0/imm32/no-inouts
35789     68/push 0/imm32/operation
35790     68/push 0/imm32/operation
35791     68/push 1/imm32
35792     89/<- %esi 4/r32/esp
35793 $test-emit-subx-stmt-primitive-register:initialize-stmt-operation:
35794     # stmt->operation = "increment"
35795     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
35796     (copy-array Heap "increment" %eax)
35797 $test-emit-subx-stmt-primitive-register:initialize-formal-var:
35798     # var formal-var/ebx: (payload var)
35799     68/push 0/imm32/register
35800     68/push 0/imm32/register
35801     68/push 0/imm32/no-stack-offset
35802     68/push 1/imm32/block-depth
35803     ff 6/subop/push *(ecx+0x10)  # Var-type + payload alloc id + handle alloc id
35804     68/push 0x11/imm32/alloc-id:fake
35805     68/push 0/imm32/name
35806     68/push 0/imm32/name
35807     68/push 0x11/imm32/alloc-id:fake:payload
35808     89/<- %ebx 4/r32/esp
35809 $test-emit-subx-stmt-primitive-register:initialize-formal-var-name:
35810     # formal-var->name = "dummy"
35811     8d/copy-address *(ebx+4) 0/r32/eax  # Var-name + 4
35812     (copy-array Heap "dummy" %eax)
35813 $test-emit-subx-stmt-primitive-register:initialize-formal-register:
35814     # formal-var->register = "*"
35815     8d/copy-address *(ebx+0x1c) 0/r32/eax  # Var-register + 4
35816     (copy-array Heap "*" %eax)  # Any-register
35817 $test-emit-subx-stmt-primitive-register:initialize-var-list:
35818     # var formal-outputs/ebx: (payload list var)
35819     68/push 0/imm32/next
35820     68/push 0/imm32/next
35821     53/push-ebx/formal-var
35822     68/push 0x11/imm32/alloc-id:fake
35823     68/push 0x11/imm32/alloc-id:fake:payload
35824     89/<- %ebx 4/r32/esp
35825 $test-emit-subx-stmt-primitive-register:initialize-primitive:
35826     # var primitives/ebx: (addr primitive)
35827     68/push 0/imm32/next
35828     68/push 0/imm32/next
35829     68/push 0/imm32/no-x32
35830     68/push 0/imm32/no-xm32
35831     68/push 0/imm32/no-disp32
35832     68/push 0/imm32/no-imm8
35833     68/push 0/imm32/no-imm32
35834     68/push 0/imm32/no-r32
35835     68/push 3/imm32/rm32-is-first-output
35836     68/push 0/imm32/subx-name
35837     68/push 0/imm32/subx-name
35838     53/push-ebx/outputs
35839     68/push 0x11/imm32/alloc-id:fake
35840     68/push 0/imm32/no-inouts
35841     68/push 0/imm32/no-inouts
35842     68/push 0/imm32/name
35843     68/push 0/imm32/name
35844     89/<- %ebx 4/r32/esp
35845 $test-emit-subx-stmt-primitive-register:initialize-primitive-name:
35846     # primitives->name = "increment"
35847     (copy-array Heap "increment" %ebx)  # Primitive-name
35848 $test-emit-subx-stmt-primitive-register:initialize-primitive-subx-name:
35849     # primitives->subx-name = "ff 0/subop/increment"
35850     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
35851     (copy-array Heap "ff 0/subop/increment" %eax)
35852     # convert
35853     c7 0/subop/copy *Curr-block-depth 0/imm32
35854     (emit-subx-stmt _test-output-buffered-file %esi %ebx 0 Stderr 0)
35855     (flush _test-output-buffered-file)
35856 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
35862     # check output
35863     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-primitive-register")
35864     # . epilogue
35865     89/<- %esp 5/r32/ebp
35866     5d/pop-to-ebp
35867     c3/return
35868 
35869 test-emit-subx-stmt-select-primitive:
35870     # Select the right primitive between overloads.
35871     #   foo <- increment
35872     # =>
35873     #   ff 0/subop/increment %eax  # sub-optimal, but should suffice
35874     #
35875     # There's a variable on the var stack as follows:
35876     #   name: 'foo'
35877     #   type: int
35878     #   register: 'eax'
35879     #
35880     # There's two primitives, as follows:
35881     #   - name: 'increment'
35882     #     out: int/reg
35883     #     value: 'ff 0/subop/increment'
35884     #   - name: 'increment'
35885     #     inout: int/mem
35886     #     value: 'ff 0/subop/increment'
35887     #
35888     # . prologue
35889     55/push-ebp
35890     89/<- %ebp 4/r32/esp
35891     # setup
35892     (clear-stream _test-output-stream)
35893     (clear-stream $_test-output-buffered-file->buffer)
35894 $test-emit-subx-stmt-select-primitive:initialize-type:
35895     # var type/ecx: (payload type-tree) = int
35896     68/push 0/imm32/right:null
35897     68/push 0/imm32/right:null
35898     68/push 0/imm32/left:unused
35899     68/push 1/imm32/value:int
35900     68/push 1/imm32/is-atom?:true
35901     68/push 0x11/imm32/alloc-id:fake:payload
35902     89/<- %ecx 4/r32/esp
35903 $test-emit-subx-stmt-select-primitive:initialize-var:
35904     # var var-foo/ecx: (payload var)
35905     68/push 0/imm32/register
35906     68/push 0/imm32/register
35907     68/push 0/imm32/no-stack-offset
35908     68/push 1/imm32/block-depth
35909     51/push-ecx
35910     68/push 0x11/imm32/alloc-id:fake
35911     68/push 0/imm32/name
35912     68/push 0/imm32/name
35913     68/push 0x11/imm32/alloc-id:fake:payload
35914     89/<- %ecx 4/r32/esp
35915 $test-emit-subx-stmt-select-primitive:initialize-var-name:
35916     # var-foo->name = "foo"
35917     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
35918     (copy-array Heap "foo" %eax)
35919 $test-emit-subx-stmt-select-primitive:initialize-var-register:
35920     # var-foo->register = "eax"
35921     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
35922     (copy-array Heap "eax" %eax)
35923 $test-emit-subx-stmt-select-primitive:initialize-stmt-var:
35924     # var operand/ebx: (payload stmt-var)
35925     68/push 0/imm32/is-deref:false
35926     68/push 0/imm32/next
35927     68/push 0/imm32/next
35928     51/push-ecx/var-foo
35929     68/push 0x11/imm32/alloc-id:fake
35930     68/push 0x11/imm32/alloc-id:fake:payload
35931     89/<- %ebx 4/r32/esp
35932 $test-emit-subx-stmt-select-primitive:initialize-stmt:
35933     # var stmt/esi: (addr statement)
35934     53/push-ebx/outputs
35935     68/push 0x11/imm32/alloc-id:fake
35936     68/push 0/imm32/no-inouts
35937     68/push 0/imm32/no-inouts
35938     68/push 0/imm32/operation
35939     68/push 0/imm32/operation
35940     68/push 1/imm32
35941     89/<- %esi 4/r32/esp
35942 $test-emit-subx-stmt-select-primitive:initialize-stmt-operation:
35943     # stmt->operation = "increment"
35944     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
35945     (copy-array Heap "increment" %eax)
35946 $test-emit-subx-stmt-select-primitive:initialize-formal-var:
35947     # var formal-var/ebx: (payload var)
35948     68/push 0/imm32/register
35949     68/push 0/imm32/register
35950     68/push 0/imm32/no-stack-offset
35951     68/push 1/imm32/block-depth
35952     ff 6/subop/push *(ecx+0x10)  # Var-type + payload alloc id + handle alloc id
35953     68/push 0x11/imm32/alloc-id:fake
35954     68/push 0/imm32/name
35955     68/push 0/imm32/name
35956     68/push 0x11/imm32/alloc-id:fake:payload
35957     89/<- %ebx 4/r32/esp
35958 $test-emit-subx-stmt-select-primitive:initialize-formal-var-name:
35959     # formal-var->name = "dummy"
35960     8d/copy-address *(ebx+4) 0/r32/eax  # Var-name + 4
35961     (copy-array Heap "dummy" %eax)
35962 $test-emit-subx-stmt-select-primitive:initialize-formal-register:
35963     # formal-var->register = "*"
35964     8d/copy-address *(ebx+0x1c) 0/r32/eax  # Var-register + 4
35965     (copy-array Heap "*" %eax)  # Any-register
35966 $test-emit-subx-stmt-select-primitive:initialize-var-list:
35967     # var formal-outputs/ebx: (payload list var)
35968     68/push 0/imm32/next
35969     68/push 0/imm32/next
35970     53/push-ebx/formal-var
35971     68/push 0x11/imm32/alloc-id:fake
35972     68/push 0x11/imm32/alloc-id:fake:payload
35973     89/<- %ebx 4/r32/esp
35974 $test-emit-subx-stmt-select-primitive:initialize-primitive2:
35975     # var primitive2/edi: (payload primitive)
35976     68/push 0/imm32/next
35977     68/push 0/imm32/next
35978     68/push 0/imm32/no-x32
35979     68/push 0/imm32/no-xm32
35980     68/push 0/imm32/no-disp32
35981     68/push 0/imm32/no-imm8
35982     68/push 0/imm32/no-imm32
35983     68/push 0/imm32/no-r32
35984     68/push 3/imm32/rm32-is-first-output
35985     68/push 0/imm32/subx-name
35986     68/push 0/imm32/subx-name
35987     53/push-ebx/outputs
35988     68/push 0x11/imm32/alloc-id:fake
35989     68/push 0/imm32/no-inouts
35990     68/push 0/imm32/no-inouts
35991     68/push 0/imm32/name
35992     68/push 0/imm32/name
35993     68/push 0x11/imm32/alloc-id:fake:payload
35994     89/<- %edi 4/r32/esp
35995 $test-emit-subx-stmt-select-primitive:initialize-primitive2-name:
35996     # primitives->name = "increment"
35997     8d/copy-address *(edi+4) 0/r32/eax  # Primitive-name + 4
35998     (copy-array Heap "increment" %eax)
35999 $test-emit-subx-stmt-select-primitive:initialize-primitive2-subx-name:
36000     # primitives->subx-name = "ff 0/subop/increment"
36001     8d/copy-address *(edi+0x1c) 0/r32/eax  # Primitive-subx-name + 4
36002     (copy-array Heap "ff 0/subop/increment" %eax)
36003 $test-emit-subx-stmt-select-primitive:initialize-primitive:
36004     # var primitives/ebx: (addr primitive)
36005     57/push-edi
36006     68/push 0x11/imm32/alloc-id:fake
36007     68/push 0/imm32/no-x32
36008     68/push 0/imm32/no-xm32
36009     68/push 0/imm32/no-disp32
36010     68/push 0/imm32/no-imm8
36011     68/push 0/imm32/no-imm32
36012     68/push 0/imm32/no-r32
36013     68/push 1/imm32/rm32-is-first-inout
36014     68/push 0/imm32/subx-name
36015     68/push 0/imm32/subx-name
36016     68/push 0/imm32/no-outputs
36017     68/push 0/imm32/no-outputs
36018     53/push-ebx/inouts  # hack: reuse stmt-var from call stmt as (list var) in function declaration
36019     68/push 0x11/imm32/alloc-id:fake
36020     68/push 0/imm32/name
36021     68/push 0/imm32/name
36022     89/<- %ebx 4/r32/esp
36023 $test-emit-subx-stmt-select-primitive:initialize-primitive-name:
36024     # primitives->name = "increment"
36025     (copy-array Heap "increment" %ebx)  # Primitive-name
36026 $test-emit-subx-stmt-select-primitive:initialize-primitive-subx-name:
36027     # primitives->subx-name = "ff 0/subop/increment"
36028     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
36029     (copy-array Heap "ff 0/subop/increment" %eax)
36030     # convert
36031     c7 0/subop/copy *Curr-block-depth 0/imm32
36032     (emit-subx-stmt _test-output-buffered-file %esi %ebx 0 Stderr 0)
36033     (flush _test-output-buffered-file)
36034 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
36040     # check output
36041     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-select-primitive")
36042     # . epilogue
36043     89/<- %esp 5/r32/ebp
36044     5d/pop-to-ebp
36045     c3/return
36046 
36047 test-emit-subx-stmt-select-primitive-2:
36048     # Select the right primitive between overloads.
36049     #   increment foo
36050     # =>
36051     #   ff 0/subop/increment %eax  # sub-optimal, but should suffice
36052     #
36053     # There's a variable on the var stack as follows:
36054     #   name: 'foo'
36055     #   type: int
36056     #   register: 'eax'
36057     #
36058     # There's two primitives, as follows:
36059     #   - name: 'increment'
36060     #     out: int/reg
36061     #     value: 'ff 0/subop/increment'
36062     #   - name: 'increment'
36063     #     inout: int/mem
36064     #     value: 'ff 0/subop/increment'
36065     #
36066     # . prologue
36067     55/push-ebp
36068     89/<- %ebp 4/r32/esp
36069     # setup
36070     (clear-stream _test-output-stream)
36071     (clear-stream $_test-output-buffered-file->buffer)
36072 $test-emit-subx-stmt-select-primitive-2:initialize-type:
36073     # var type/ecx: (payload type-tree) = int
36074     68/push 0/imm32/right:null
36075     68/push 0/imm32/right:null
36076     68/push 0/imm32/left:unused
36077     68/push 1/imm32/value:int
36078     68/push 1/imm32/is-atom?:true
36079     68/push 0x11/imm32/alloc-id:fake:payload
36080     89/<- %ecx 4/r32/esp
36081 $test-emit-subx-stmt-select-primitive-2:initialize-var:
36082     # var var-foo/ecx: (payload var)
36083     68/push 0/imm32/register
36084     68/push 0/imm32/register
36085     68/push 0/imm32/no-stack-offset
36086     68/push 1/imm32/block-depth
36087     51/push-ecx
36088     68/push 0x11/imm32/alloc-id:fake
36089     68/push 0/imm32/name
36090     68/push 0/imm32/name
36091     68/push 0x11/imm32/alloc-id:fake:payload
36092     89/<- %ecx 4/r32/esp
36093 $test-emit-subx-stmt-select-primitive-2:initialize-var-name:
36094     # var-foo->name = "foo"
36095     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
36096     (copy-array Heap "foo" %eax)
36097 $test-emit-subx-stmt-select-primitive-2:initialize-var-register:
36098     # var-foo->register = "eax"
36099     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
36100     (copy-array Heap "eax" %eax)
36101 $test-emit-subx-stmt-select-primitive-2:initialize-stmt-var:
36102     # var operand/ebx: (payload stmt-var)
36103     68/push 0/imm32/is-deref:false
36104     68/push 0/imm32/next
36105     68/push 0/imm32/next
36106     51/push-ecx/var-foo
36107     68/push 0x11/imm32/alloc-id:fake
36108     68/push 0x11/imm32/alloc-id:fake:payload
36109     89/<- %ebx 4/r32/esp
36110 $test-emit-subx-stmt-select-primitive-2:initialize-stmt:
36111     # var stmt/esi: (addr statement)
36112     68/push 0/imm32/no-outputs
36113     68/push 0/imm32/no-outputs
36114     53/push-ebx/inouts
36115     68/push 0x11/imm32/alloc-id:fake
36116     68/push 0/imm32/operation
36117     68/push 0/imm32/operation
36118     68/push 1/imm32
36119     89/<- %esi 4/r32/esp
36120 $test-emit-subx-stmt-select-primitive-2:initialize-stmt-operation:
36121     # stmt->operation = "increment"
36122     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
36123     (copy-array Heap "increment" %eax)
36124 $test-emit-subx-stmt-select-primitive-2:initialize-formal-var:
36125     # var formal-var/ebx: (payload var)
36126     68/push 0/imm32/register
36127     68/push 0/imm32/register
36128     68/push 0/imm32/no-stack-offset
36129     68/push 1/imm32/block-depth
36130     ff 6/subop/push *(ecx+0x10)  # Var-type + payload alloc id + handle alloc id
36131     68/push 0x11/imm32/alloc-id:fake
36132     68/push 0/imm32/name
36133     68/push 0/imm32/name
36134     68/push 0x11/imm32/alloc-id:fake:payload
36135     89/<- %ebx 4/r32/esp
36136 $test-emit-subx-stmt-select-primitive-2:initialize-formal-var-name:
36137     # formal-var->name = "dummy"
36138     8d/copy-address *(ebx+4) 0/r32/eax  # Var-name + 4
36139     (copy-array Heap "dummy" %eax)
36140 $test-emit-subx-stmt-select-primitive-2:initialize-formal-register:
36141     # formal-var->register = "*"
36142     8d/copy-address *(ebx+0x1c) 0/r32/eax  # Var-register + 4
36143     (copy-array Heap "*" %eax)  # Any-register
36144 $test-emit-subx-stmt-select-primitive-2:initialize-var-list:
36145     # var formal-outputs/ebx: (payload list stmt-var)
36146     68/push 0/imm32/next
36147     68/push 0/imm32/next
36148     53/push-ebx/formal-var
36149     68/push 0x11/imm32/alloc-id:fake
36150     68/push 0x11/imm32/alloc-id:fake:payload
36151     89/<- %ebx 4/r32/esp
36152 $test-emit-subx-stmt-select-primitive-2:initialize-primitive2:
36153     # var primitive2/edi: (payload primitive)
36154     68/push 0/imm32/next
36155     68/push 0/imm32/next
36156     68/push 0/imm32/no-x32
36157     68/push 0/imm32/no-xm32
36158     68/push 0/imm32/no-disp32
36159     68/push 0/imm32/no-imm8
36160     68/push 0/imm32/no-imm32
36161     68/push 0/imm32/no-r32
36162     68/push 3/imm32/rm32-is-first-output
36163     68/push 0/imm32/subx-name
36164     68/push 0/imm32/subx-name
36165     53/push-ebx/outputs
36166     68/push 0x11/imm32/alloc-id:fake
36167     68/push 0/imm32/no-inouts
36168     68/push 0/imm32/no-inouts
36169     68/push 0/imm32/name
36170     68/push 0/imm32/name
36171     68/push 0x11/imm32/alloc-id:fake:payload
36172     89/<- %edi 4/r32/esp
36173 $test-emit-subx-stmt-select-primitive-2:initialize-primitive2-name:
36174     # primitives->name = "increment"
36175     8d/copy-address *(edi+4) 0/r32/eax  # Primitive-name + 4
36176     (copy-array Heap "increment" %eax)
36177 $test-emit-subx-stmt-select-primitive-2:initialize-primitive2-subx-name:
36178     # primitives->subx-name = "ff 0/subop/increment"
36179     8d/copy-address *(edi+0x1c) 0/r32/eax  # Primitive-subx-name + 4
36180     (copy-array Heap "ff 0/subop/increment" %eax)
36181 $test-emit-subx-stmt-select-primitive-2:initialize-primitive:
36182     # var primitives/ebx: (addr primitive)
36183     57/push-edi
36184     68/push 0x11/imm32/alloc-id:fake
36185     68/push 0/imm32/no-x32
36186     68/push 0/imm32/no-xm32
36187     68/push 0/imm32/no-disp32
36188     68/push 0/imm32/no-imm8
36189     68/push 0/imm32/no-imm32
36190     68/push 0/imm32/no-r32
36191     68/push 1/imm32/rm32-is-first-inout
36192     68/push 0/imm32/subx-name
36193     68/push 0/imm32/subx-name
36194     68/push 0/imm32/no-outputs
36195     68/push 0/imm32/no-outputs
36196     53/push-ebx/inouts  # hack: reuse stmt-var from call stmt as (list var) in function declaration
36197     68/push 0x11/imm32/alloc-id:fake
36198     68/push 0/imm32/name
36199     68/push 0/imm32/name
36200     89/<- %ebx 4/r32/esp
36201 $test-emit-subx-stmt-select-primitive-2:initialize-primitive-name:
36202     # primitives->name = "increment"
36203     (copy-array Heap "increment" %ebx)  # Primitive-name
36204 $test-emit-subx-stmt-select-primitive-2:initialize-primitive-subx-name:
36205     # primitives->subx-name = "ff 0/subop/increment"
36206     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
36207     (copy-array Heap "ff 0/subop/increment" %eax)
36208     # convert
36209     c7 0/subop/copy *Curr-block-depth 0/imm32
36210     (emit-subx-stmt _test-output-buffered-file %esi %ebx 0 Stderr 0)
36211     (flush _test-output-buffered-file)
36212 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
36218     # check output
36219     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-select-primitive-2")
36220     # . epilogue
36221     89/<- %esp 5/r32/ebp
36222     5d/pop-to-ebp
36223     c3/return
36224 
36225 test-increment-register:
36226     # Select the right register between overloads.
36227     #   foo <- increment
36228     # =>
36229     #   50/increment-eax
36230     #
36231     # There's a variable on the var stack as follows:
36232     #   name: 'foo'
36233     #   type: int
36234     #   register: 'eax'
36235     #
36236     # Primitives are the global definitions.
36237     #
36238     # . prologue
36239     55/push-ebp
36240     89/<- %ebp 4/r32/esp
36241     # setup
36242     (clear-stream _test-output-stream)
36243     (clear-stream $_test-output-buffered-file->buffer)
36244 $test-increment-register:initialize-type:
36245     # var type/ecx: (payload type-tree) = int
36246     68/push 0/imm32/right:null
36247     68/push 0/imm32/right:null
36248     68/push 0/imm32/left:unused
36249     68/push 1/imm32/value:int
36250     68/push 1/imm32/is-atom?:true
36251     68/push 0x11/imm32/alloc-id:fake:payload
36252     89/<- %ecx 4/r32/esp
36253 $test-increment-register:initialize-var:
36254     # var var-foo/ecx: (payload var)
36255     68/push 0/imm32/register
36256     68/push 0/imm32/register
36257     68/push 0/imm32/no-stack-offset
36258     68/push 1/imm32/block-depth
36259     51/push-ecx
36260     68/push 0x11/imm32/alloc-id:fake
36261     68/push 0/imm32/name
36262     68/push 0/imm32/name
36263     68/push 0x11/imm32/alloc-id:fake:payload
36264     89/<- %ecx 4/r32/esp
36265 $test-increment-register:initialize-var-name:
36266     # var-foo->name = "foo"
36267     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
36268     (copy-array Heap "foo" %eax)
36269 $test-increment-register:initialize-var-register:
36270     # var-foo->register = "eax"
36271     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
36272     (copy-array Heap "eax" %eax)
36273 $test-increment-register:initialize-stmt-var:
36274     # var operand/ebx: (payload stmt-var)
36275     68/push 0/imm32/is-deref:false
36276     68/push 0/imm32/next
36277     68/push 0/imm32/next
36278     51/push-ecx/var-foo
36279     68/push 0x11/imm32/alloc-id:fake
36280     68/push 0x11/imm32/alloc-id:fake:payload
36281     89/<- %ebx 4/r32/esp
36282 $test-increment-register:initialize-stmt:
36283     # var stmt/esi: (addr statement)
36284     53/push-ebx/outputs
36285     68/push 0x11/imm32/alloc-id:fake
36286     68/push 0/imm32/no-inouts
36287     68/push 0/imm32/no-inouts
36288     68/push 0/imm32/operation
36289     68/push 0/imm32/operation
36290     68/push 1/imm32
36291     89/<- %esi 4/r32/esp
36292 $test-increment-register:initialize-stmt-operation:
36293     # stmt->operation = "increment"
36294     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
36295     (copy-array Heap "increment" %eax)
36296     # convert
36297     c7 0/subop/copy *Curr-block-depth 0/imm32
36298     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
36299     (flush _test-output-buffered-file)
36300 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
36306     # check output
36307     (check-next-stream-line-equal _test-output-stream "40/increment-eax" "F - test-increment-register")
36308     # . epilogue
36309     89/<- %esp 5/r32/ebp
36310     5d/pop-to-ebp
36311     c3/return
36312 
36313 test-add-reg-to-reg:
36314     #   var1/reg <- add var2/reg
36315     # =>
36316     #   01/add-to %var1 var2
36317     #
36318     # . prologue
36319     55/push-ebp
36320     89/<- %ebp 4/r32/esp
36321     # setup
36322     (clear-stream _test-output-stream)
36323     (clear-stream $_test-output-buffered-file->buffer)
36324 $test-add-reg-to-reg:initialize-type:
36325     # var type/ecx: (payload type-tree) = int
36326     68/push 0/imm32/right:null
36327     68/push 0/imm32/right:null
36328     68/push 0/imm32/left:unused
36329     68/push 1/imm32/value:int
36330     68/push 1/imm32/is-atom?:true
36331     68/push 0x11/imm32/alloc-id:fake:payload
36332     89/<- %ecx 4/r32/esp
36333 $test-add-reg-to-reg:initialize-var1:
36334     # var var1/ecx: (payload var)
36335     68/push 0/imm32/register
36336     68/push 0/imm32/register
36337     68/push 0/imm32/no-stack-offset
36338     68/push 1/imm32/block-depth
36339     51/push-ecx
36340     68/push 0x11/imm32/alloc-id:fake
36341     68/push 0/imm32/name
36342     68/push 0/imm32/name
36343     68/push 0x11/imm32/alloc-id:fake:payload
36344     89/<- %ecx 4/r32/esp
36345 $test-add-reg-to-reg:initialize-var1-name:
36346     # var1->name = "var1"
36347     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
36348     (copy-array Heap "var1" %eax)
36349 $test-add-reg-to-reg:initialize-var1-register:
36350     # var1->register = "eax"
36351     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
36352     (copy-array Heap "eax" %eax)
36353 $test-add-reg-to-reg:initialize-var2:
36354     # var var2/edx: (payload var)
36355     68/push 0/imm32/register
36356     68/push 0/imm32/register
36357     68/push 0/imm32/no-stack-offset
36358     68/push 1/imm32/block-depth
36359     ff 6/subop/push *(ecx+0x10)
36360     68/push 0x11/imm32/alloc-id:fake
36361     68/push 0/imm32/name
36362     68/push 0/imm32/name
36363     68/push 0x11/imm32/alloc-id:fake:payload
36364     89/<- %edx 4/r32/esp
36365 $test-add-reg-to-reg:initialize-var2-name:
36366     # var2->name = "var2"
36367     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
36368     (copy-array Heap "var2" %eax)
36369 $test-add-reg-to-reg:initialize-var2-register:
36370     # var2->register = "ecx"
36371     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
36372     (copy-array Heap "ecx" %eax)
36373 $test-add-reg-to-reg:initialize-inouts:
36374     # var inouts/esi: (payload stmt-var) = [var2]
36375     68/push 0/imm32/is-deref:false
36376     68/push 0/imm32/next
36377     68/push 0/imm32/next
36378     52/push-edx/var2
36379     68/push 0x11/imm32/alloc-id:fake
36380     68/push 0x11/imm32/alloc-id:fake:payload
36381     89/<- %esi 4/r32/esp
36382 $test-add-reg-to-reg:initialize-outputs:
36383     # var outputs/edi: (payload stmt-var) = [var1]
36384     68/push 0/imm32/is-deref:false
36385     68/push 0/imm32/next
36386     68/push 0/imm32/next
36387     51/push-ecx/var1
36388     68/push 0x11/imm32/alloc-id:fake
36389     68/push 0x11/imm32/alloc-id:fake:payload
36390     89/<- %edi 4/r32/esp
36391 $test-add-reg-to-reg:initialize-stmt:
36392     # var stmt/esi: (addr statement)
36393     68/push 0/imm32/next
36394     68/push 0/imm32/next
36395     57/push-edi/outputs
36396     68/push 0x11/imm32/alloc-id:fake
36397     56/push-esi/inouts
36398     68/push 0x11/imm32/alloc-id:fake
36399     68/push 0/imm32/operation
36400     68/push 0/imm32/operation
36401     68/push 1/imm32/tag:stmt1
36402     89/<- %esi 4/r32/esp
36403 $test-add-reg-to-reg:initialize-stmt-operation:
36404     # stmt->operation = "add"
36405     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
36406     (copy-array Heap "add" %eax)
36407     # convert
36408     c7 0/subop/copy *Curr-block-depth 0/imm32
36409     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
36410     (flush _test-output-buffered-file)
36411 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
36417     # check output
36418     (check-next-stream-line-equal _test-output-stream "01/add-to %eax 0x00000001/r32" "F - test-add-reg-to-reg")
36419     # . epilogue
36420     89/<- %esp 5/r32/ebp
36421     5d/pop-to-ebp
36422     c3/return
36423 
36424 test-add-reg-to-mem:
36425     #   add-to var1 var2/reg
36426     # =>
36427     #   01/add-to *(ebp+__) var2
36428     #
36429     # . prologue
36430     55/push-ebp
36431     89/<- %ebp 4/r32/esp
36432     # setup
36433     (clear-stream _test-output-stream)
36434     (clear-stream $_test-output-buffered-file->buffer)
36435 $test-add-reg-to-mem:initialize-type:
36436     # var type/ecx: (payload type-tree) = int
36437     68/push 0/imm32/right:null
36438     68/push 0/imm32/right:null
36439     68/push 0/imm32/left:unused
36440     68/push 1/imm32/value:int
36441     68/push 1/imm32/is-atom?:true
36442     68/push 0x11/imm32/alloc-id:fake:payload
36443     89/<- %ecx 4/r32/esp
36444 $test-add-reg-to-mem:initialize-var1:
36445     # var var1/ecx: (payload var)
36446     68/push 0/imm32/register
36447     68/push 0/imm32/register
36448     68/push 8/imm32/stack-offset
36449     68/push 1/imm32/block-depth
36450     51/push-ecx
36451     68/push 0x11/imm32/alloc-id:fake
36452     68/push 0/imm32/name
36453     68/push 0/imm32/name
36454     68/push 0x11/imm32/alloc-id:fake:payload
36455     89/<- %ecx 4/r32/esp
36456 $test-add-reg-to-mem:initialize-var1-name:
36457     # var1->name = "var1"
36458     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
36459     (copy-array Heap "var1" %eax)
36460 $test-add-reg-to-mem:initialize-var2:
36461     # var var2/edx: (payload var)
36462     68/push 0/imm32/register
36463     68/push 0/imm32/register
36464     68/push 0/imm32/no-stack-offset
36465     68/push 1/imm32/block-depth
36466     ff 6/subop/push *(ecx+0x10)
36467     68/push 0x11/imm32/alloc-id:fake
36468     68/push 0/imm32/name
36469     68/push 0/imm32/name
36470     68/push 0x11/imm32/alloc-id:fake:payload
36471     89/<- %edx 4/r32/esp
36472 $test-add-reg-to-mem:initialize-var2-name:
36473     # var2->name = "var2"
36474     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
36475     (copy-array Heap "var2" %eax)
36476 $test-add-reg-to-mem:initialize-var2-register:
36477     # var2->register = "ecx"
36478     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
36479     (copy-array Heap "ecx" %eax)
36480 $test-add-reg-to-mem:initialize-inouts:
36481     # var inouts/esi: (payload stmt-var) = [var2]
36482     68/push 0/imm32/is-deref:false
36483     68/push 0/imm32/next
36484     68/push 0/imm32/next
36485     52/push-edx/var2
36486     68/push 0x11/imm32/alloc-id:fake
36487     68/push 0x11/imm32/alloc-id:fake:payload
36488     89/<- %esi 4/r32/esp
36489     # inouts = [var1, var2]
36490     68/push 0/imm32/is-deref:false
36491     56/push-esi/next
36492     68/push 0x11/imm32/alloc-id:fake
36493     51/push-ecx/var1
36494     68/push 0x11/imm32/alloc-id:fake
36495     68/push 0x11/imm32/alloc-id:fake:payload
36496     89/<- %esi 4/r32/esp
36497 $test-add-reg-to-mem:initialize-stmt:
36498     # var stmt/esi: (addr statement)
36499     68/push 0/imm32/next
36500     68/push 0/imm32/next
36501     68/push 0/imm32/outputs
36502     68/push 0/imm32/outputs
36503     56/push-esi/inouts
36504     68/push 0x11/imm32/alloc-id:fake
36505     68/push 0/imm32/operation
36506     68/push 0/imm32/operation
36507     68/push 1/imm32/tag:stmt1
36508     89/<- %esi 4/r32/esp
36509 $test-add-reg-to-mem:initialize-stmt-operation:
36510     # stmt->operation = "add-to"
36511     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
36512     (copy-array Heap "add-to" %eax)
36513     # convert
36514     c7 0/subop/copy *Curr-block-depth 0/imm32
36515     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
36516     (flush _test-output-buffered-file)
36517 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
36523     # check output
36524     (check-next-stream-line-equal _test-output-stream "01/add-to *(ebp+0x00000008) 0x00000001/r32" "F - test-add-reg-to-mem")
36525     # . epilogue
36526     89/<- %esp 5/r32/ebp
36527     5d/pop-to-ebp
36528     c3/return
36529 
36530 test-add-mem-to-reg:
36531     #   var1/reg <- add var2
36532     # =>
36533     #   03/add *(ebp+__) var1
36534     #
36535     # . prologue
36536     55/push-ebp
36537     89/<- %ebp 4/r32/esp
36538     # setup
36539     (clear-stream _test-output-stream)
36540     (clear-stream $_test-output-buffered-file->buffer)
36541 $test-add-mem-to-reg:initialize-type:
36542     # var type/ecx: (payload type-tree) = int
36543     68/push 0/imm32/right:null
36544     68/push 0/imm32/right:null
36545     68/push 0/imm32/left:unused
36546     68/push 1/imm32/value:int
36547     68/push 1/imm32/is-atom?:true
36548     68/push 0x11/imm32/alloc-id:fake:payload
36549     89/<- %ecx 4/r32/esp
36550 $test-add-mem-to-reg:initialize-var:
36551     # var var1/ecx: (payload var)
36552     68/push 0/imm32/register
36553     68/push 0/imm32/register
36554     68/push 0/imm32/no-stack-offset
36555     68/push 1/imm32/block-depth
36556     51/push-ecx
36557     68/push 0x11/imm32/alloc-id:fake
36558     68/push 0/imm32/name
36559     68/push 0/imm32/name
36560     68/push 0x11/imm32/alloc-id:fake:payload
36561     89/<- %ecx 4/r32/esp
36562 $test-add-mem-to-reg:initialize-var-name:
36563     # var1->name = "foo"
36564     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
36565     (copy-array Heap "var1" %eax)
36566 $test-add-mem-to-reg:initialize-var-register:
36567     # var1->register = "eax"
36568     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
36569     (copy-array Heap "eax" %eax)
36570 $test-add-mem-to-reg:initialize-var2:
36571     # var var2/edx: (payload var)
36572     68/push 0/imm32/register
36573     68/push 0/imm32/register
36574     68/push 8/imm32/stack-offset
36575     68/push 1/imm32/block-depth
36576     ff 6/subop/push *(ecx+0x10)
36577     68/push 0x11/imm32/alloc-id:fake
36578     68/push 0/imm32/name
36579     68/push 0/imm32/name
36580     68/push 0x11/imm32/alloc-id:fake:payload
36581     89/<- %edx 4/r32/esp
36582 $test-add-mem-to-reg:initialize-var2-name:
36583     # var2->name = "var2"
36584     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
36585     (copy-array Heap "var2" %eax)
36586 $test-add-mem-to-reg:initialize-inouts:
36587     # var inouts/esi: (payload stmt-var) = [var2]
36588     68/push 0/imm32/is-deref:false
36589     68/push 0/imm32/next
36590     68/push 0/imm32/next
36591     52/push-edx/var2
36592     68/push 0x11/imm32/alloc-id:fake
36593     68/push 0x11/imm32/alloc-id:fake:payload
36594     89/<- %esi 4/r32/esp
36595 $test-add-mem-to-reg:initialize-outputs:
36596     # var outputs/edi: (payload stmt-var) = [var1]
36597     68/push 0/imm32/is-deref:false
36598     68/push 0/imm32/next
36599     68/push 0/imm32/next
36600     51/push-ecx/var1
36601     68/push 0x11/imm32/alloc-id:fake
36602     68/push 0x11/imm32/alloc-id:fake:payload
36603     89/<- %edi 4/r32/esp
36604 $test-add-mem-to-reg:initialize-stmt:
36605     # var stmt/esi: (addr statement)
36606     68/push 0/imm32/next
36607     68/push 0/imm32/next
36608     57/push-edi/outputs
36609     68/push 0x11/imm32/alloc-id:fake
36610     56/push-esi/inouts
36611     68/push 0x11/imm32/alloc-id:fake
36612     68/push 0/imm32/operation
36613     68/push 0/imm32/operation
36614     68/push 1/imm32/tag:stmt1
36615     89/<- %esi 4/r32/esp
36616 $test-add-mem-to-reg:initialize-stmt-operation:
36617     # stmt->operation = "add"
36618     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
36619     (copy-array Heap "add" %eax)
36620     # convert
36621     c7 0/subop/copy *Curr-block-depth 0/imm32
36622     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
36623     (flush _test-output-buffered-file)
36624 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
36630     # check output
36631     (check-next-stream-line-equal _test-output-stream "03/add *(ebp+0x00000008) 0x00000000/r32" "F - test-add-mem-to-reg")
36632     # . epilogue
36633     89/<- %esp 5/r32/ebp
36634     5d/pop-to-ebp
36635     c3/return
36636 
36637 test-add-literal-to-eax:
36638     #   var1/eax <- add 0x34
36639     # =>
36640     #   05/add-to-eax 0x34/imm32
36641     #
36642     # . prologue
36643     55/push-ebp
36644     89/<- %ebp 4/r32/esp
36645     # setup
36646     (clear-stream _test-output-stream)
36647     (clear-stream $_test-output-buffered-file->buffer)
36648 $test-add-literal-to-eax:initialize-var-type:
36649     # var type/ecx: (payload type-tree) = int
36650     68/push 0/imm32/right:null
36651     68/push 0/imm32/right:null
36652     68/push 0/imm32/left:unused
36653     68/push 1/imm32/value:int
36654     68/push 1/imm32/is-atom?:true
36655     68/push 0x11/imm32/alloc-id:fake:payload
36656     89/<- %ecx 4/r32/esp
36657 $test-add-literal-to-eax:initialize-var:
36658     # var v/ecx: (payload var)
36659     68/push 0/imm32/register
36660     68/push 0/imm32/register
36661     68/push 0/imm32/no-stack-offset
36662     68/push 1/imm32/block-depth
36663     51/push-ecx
36664     68/push 0x11/imm32/alloc-id:fake
36665     68/push 0/imm32/name
36666     68/push 0/imm32/name
36667     68/push 0x11/imm32/alloc-id:fake:payload
36668     89/<- %ecx 4/r32/esp
36669 $test-add-literal-to-eax:initialize-var-name:
36670     # v->name = "v"
36671     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
36672     (copy-array Heap "v" %eax)
36673 $test-add-literal-to-eax:initialize-var-register:
36674     # v->register = "eax"
36675     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
36676     (copy-array Heap "eax" %eax)
36677 $test-add-literal-to-eax:initialize-literal-type:
36678     # var type/edx: (payload type-tree) = literal
36679     68/push 0/imm32/right:null
36680     68/push 0/imm32/right:null
36681     68/push 0/imm32/left:unused
36682     68/push 0/imm32/value:literal
36683     68/push 1/imm32/is-atom?:true
36684     68/push 0x11/imm32/alloc-id:fake:payload
36685     89/<- %edx 4/r32/esp
36686 $test-add-literal-to-eax:initialize-literal:
36687     # var l/edx: (payload var)
36688     68/push 0/imm32/register
36689     68/push 0/imm32/register
36690     68/push 0/imm32/no-stack-offset
36691     68/push 1/imm32/block-depth
36692     52/push-edx
36693     68/push 0x11/imm32/alloc-id:fake
36694     68/push 0/imm32/name
36695     68/push 0/imm32/name
36696     68/push 0x11/imm32/alloc-id:fake:payload
36697     89/<- %edx 4/r32/esp
36698 $test-add-literal-to-eax:initialize-literal-value:
36699     # l->name = "0x34"
36700     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
36701     (copy-array Heap "0x34" %eax)
36702 $test-add-literal-to-eax:initialize-inouts:
36703     # var inouts/esi: (payload stmt-var) = [l]
36704     68/push 0/imm32/is-deref:false
36705     68/push 0/imm32/next
36706     68/push 0/imm32/next
36707     52/push-edx/l
36708     68/push 0x11/imm32/alloc-id:fake
36709     68/push 0x11/imm32/alloc-id:fake:payload
36710     89/<- %esi 4/r32/esp
36711 $test-add-literal-to-eax:initialize-outputs:
36712     # var outputs/edi: (payload stmt-var) = [v]
36713     68/push 0/imm32/is-deref:false
36714     68/push 0/imm32/next
36715     68/push 0/imm32/next
36716     51/push-ecx/v
36717     68/push 0x11/imm32/alloc-id:fake
36718     68/push 0x11/imm32/alloc-id:fake:payload
36719     89/<- %edi 4/r32/esp
36720 $test-add-literal-to-eax:initialize-stmt:
36721     # var stmt/esi: (addr statement)
36722     68/push 0/imm32/next
36723     68/push 0/imm32/next
36724     57/push-edi/outputs
36725     68/push 0x11/imm32/alloc-id:fake
36726     56/push-esi/inouts
36727     68/push 0x11/imm32/alloc-id:fake
36728     68/push 0/imm32/operation
36729     68/push 0/imm32/operation
36730     68/push 1/imm32/tag:stmt1
36731     89/<- %esi 4/r32/esp
36732 $test-add-literal-to-eax:initialize-stmt-operation:
36733     # stmt->operation = "add"
36734     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
36735     (copy-array Heap "add" %eax)
36736     # convert
36737     c7 0/subop/copy *Curr-block-depth 0/imm32
36738     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
36739     (flush _test-output-buffered-file)
36740 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
36746     # check output
36747     (check-next-stream-line-equal _test-output-stream "05/add-to-eax 0x34/imm32" "F - test-add-literal-to-eax")
36748     # . epilogue
36749     89/<- %esp 5/r32/ebp
36750     5d/pop-to-ebp
36751     c3/return
36752 
36753 test-add-literal-to-reg:
36754     #   var1/ecx <- add 0x34
36755     # =>
36756     #   81 0/subop/add %ecx 0x34/imm32
36757     #
36758     # . prologue
36759     55/push-ebp
36760     89/<- %ebp 4/r32/esp
36761     # setup
36762     (clear-stream _test-output-stream)
36763     (clear-stream $_test-output-buffered-file->buffer)
36764 $test-add-literal-to-reg:initialize-var-type:
36765     # var type/ecx: (payload type-tree) = int
36766     68/push 0/imm32/right:null
36767     68/push 0/imm32/right:null
36768     68/push 0/imm32/left:unused
36769     68/push 1/imm32/value:int
36770     68/push 1/imm32/is-atom?:true
36771     68/push 0x11/imm32/alloc-id:fake:payload
36772     89/<- %ecx 4/r32/esp
36773 $test-add-literal-to-reg:initialize-var:
36774     # var v/ecx: (payload var)
36775     68/push 0/imm32/register
36776     68/push 0/imm32/register
36777     68/push 0/imm32/no-stack-offset
36778     68/push 1/imm32/block-depth
36779     51/push-ecx
36780     68/push 0x11/imm32/alloc-id:fake
36781     68/push 0/imm32/name
36782     68/push 0/imm32/name
36783     68/push 0x11/imm32/alloc-id:fake:payload
36784     89/<- %ecx 4/r32/esp
36785 $test-add-literal-to-reg:initialize-var-name:
36786     # v->name = "v"
36787     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
36788     (copy-array Heap "v" %eax)
36789 $test-add-literal-to-reg:initialize-var-register:
36790     # v->register = "ecx"
36791     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
36792     (copy-array Heap "ecx" %eax)
36793 $test-add-literal-to-reg:initialize-literal-type:
36794     # var type/edx: (payload type-tree) = literal
36795     68/push 0/imm32/right:null
36796     68/push 0/imm32/right:null
36797     68/push 0/imm32/left:unused
36798     68/push 0/imm32/value:literal
36799     68/push 1/imm32/is-atom?:true
36800     68/push 0x11/imm32/alloc-id:fake:payload
36801     89/<- %edx 4/r32/esp
36802 $test-add-literal-to-reg:initialize-literal:
36803     # var l/edx: (payload var)
36804     68/push 0/imm32/register
36805     68/push 0/imm32/register
36806     68/push 0/imm32/no-stack-offset
36807     68/push 1/imm32/block-depth
36808     52/push-edx
36809     68/push 0x11/imm32/alloc-id:fake
36810     68/push 0/imm32/name
36811     68/push 0/imm32/name
36812     68/push 0x11/imm32/alloc-id:fake:payload
36813     89/<- %edx 4/r32/esp
36814 $test-add-literal-to-reg:initialize-literal-value:
36815     # l->name = "0x34"
36816     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
36817     (copy-array Heap "0x34" %eax)
36818 $test-add-literal-to-reg:initialize-inouts:
36819     # var inouts/esi: (payload stmt-var) = [l]
36820     68/push 0/imm32/is-deref:false
36821     68/push 0/imm32/next
36822     68/push 0/imm32/next
36823     52/push-edx/l
36824     68/push 0x11/imm32/alloc-id:fake
36825     68/push 0x11/imm32/alloc-id:fake:payload
36826     89/<- %esi 4/r32/esp
36827 $test-add-literal-to-reg:initialize-outputs:
36828     # var outputs/edi: (payload stmt-var) = [v]
36829     68/push 0/imm32/is-deref:false
36830     68/push 0/imm32/next
36831     68/push 0/imm32/next
36832     51/push-ecx/v
36833     68/push 0x11/imm32/alloc-id:fake
36834     68/push 0x11/imm32/alloc-id:fake:payload
36835     89/<- %edi 4/r32/esp
36836 $test-add-literal-to-reg:initialize-stmt:
36837     # var stmt/esi: (addr statement)
36838     68/push 0/imm32/next
36839     68/push 0/imm32/next
36840     57/push-edi/outputs
36841     68/push 0x11/imm32/alloc-id:fake
36842     56/push-esi/inouts
36843     68/push 0x11/imm32/alloc-id:fake
36844     68/push 0/imm32/operation
36845     68/push 0/imm32/operation
36846     68/push 1/imm32/tag:stmt1
36847     89/<- %esi 4/r32/esp
36848 $test-add-literal-to-reg:initialize-stmt-operation:
36849     # stmt->operation = "add"
36850     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
36851     (copy-array Heap "add" %eax)
36852     # convert
36853     c7 0/subop/copy *Curr-block-depth 0/imm32
36854     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
36855     (flush _test-output-buffered-file)
36856 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
36862     # check output
36863     (check-next-stream-line-equal _test-output-stream "81 0/subop/add %ecx 0x34/imm32" "F - test-add-literal-to-reg")
36864     # . epilogue
36865     89/<- %esp 5/r32/ebp
36866     5d/pop-to-ebp
36867     c3/return
36868 
36869 test-add-literal-to-mem:
36870     #   add-to var1, 0x34
36871     # =>
36872     #   81 0/subop/add %eax 0x34/imm32
36873     #
36874     # . prologue
36875     55/push-ebp
36876     89/<- %ebp 4/r32/esp
36877     # setup
36878     (clear-stream _test-output-stream)
36879     (clear-stream $_test-output-buffered-file->buffer)
36880 $test-add-literal-to-mem:initialize-type:
36881     # var type/ecx: (payload type-tree) = int
36882     68/push 0/imm32/right:null
36883     68/push 0/imm32/right:null
36884     68/push 0/imm32/left:unused
36885     68/push 1/imm32/value:int
36886     68/push 1/imm32/is-atom?:true
36887     68/push 0x11/imm32/alloc-id:fake:payload
36888     89/<- %ecx 4/r32/esp
36889 $test-add-literal-to-mem:initialize-var1:
36890     # var var1/ecx: (payload var)
36891     68/push 0/imm32/register
36892     68/push 0/imm32/register
36893     68/push 8/imm32/stack-offset
36894     68/push 1/imm32/block-depth
36895     51/push-ecx
36896     68/push 0x11/imm32/alloc-id:fake
36897     68/push 0/imm32/name
36898     68/push 0/imm32/name
36899     68/push 0x11/imm32/alloc-id:fake:payload
36900     89/<- %ecx 4/r32/esp
36901 $test-add-literal-to-mem:initialize-var1-name:
36902     # var1->name = "var1"
36903     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
36904     (copy-array Heap "var1" %eax)
36905 $test-add-literal-to-mem:initialize-literal-type:
36906     # var type/edx: (payload type-tree) = literal
36907     68/push 0/imm32/right:null
36908     68/push 0/imm32/right:null
36909     68/push 0/imm32/left:unused
36910     68/push 0/imm32/value:literal
36911     68/push 1/imm32/is-atom?:true
36912     68/push 0x11/imm32/alloc-id:fake:payload
36913     89/<- %edx 4/r32/esp
36914 $test-add-literal-to-mem:initialize-literal:
36915     # var l/edx: (payload var)
36916     68/push 0/imm32/register
36917     68/push 0/imm32/register
36918     68/push 0/imm32/no-stack-offset
36919     68/push 1/imm32/block-depth
36920     52/push-edx
36921     68/push 0x11/imm32/alloc-id:fake
36922     68/push 0/imm32/name
36923     68/push 0/imm32/name
36924     68/push 0x11/imm32/alloc-id:fake:payload
36925     89/<- %edx 4/r32/esp
36926 $test-add-literal-to-mem:initialize-literal-value:
36927     # l->name = "0x34"
36928     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
36929     (copy-array Heap "0x34" %eax)
36930 $test-add-literal-to-mem:initialize-inouts:
36931     # var inouts/esi: (payload stmt-var) = [l]
36932     68/push 0/imm32/is-deref:false
36933     68/push 0/imm32/next
36934     68/push 0/imm32/next
36935     52/push-edx/l
36936     68/push 0x11/imm32/alloc-id:fake
36937     68/push 0x11/imm32/alloc-id:fake:payload
36938     89/<- %esi 4/r32/esp
36939     # var inouts = (handle stmt-var) = [var1, var2]
36940     68/push 0/imm32/is-deref:false
36941     56/push-esi/next
36942     68/push 0x11/imm32/alloc-id:fake
36943     51/push-ecx/var1
36944     68/push 0x11/imm32/alloc-id:fake
36945     68/push 0x11/imm32/alloc-id:fake:payload
36946     89/<- %esi 4/r32/esp
36947 $test-add-literal-to-mem:initialize-stmt:
36948     # var stmt/esi: (addr statement)
36949     68/push 0/imm32/next
36950     68/push 0/imm32/next
36951     68/push 0/imm32/outputs
36952     68/push 0/imm32/outputs
36953     56/push-esi/inouts
36954     68/push 0x11/imm32/alloc-id:fake
36955     68/push 0/imm32/operation
36956     68/push 0/imm32/operation
36957     68/push 1/imm32/tag:stmt1
36958     89/<- %esi 4/r32/esp
36959 $test-add-literal-to-mem:initialize-stmt-operation:
36960     # stmt->operation = "add-to"
36961     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
36962     (copy-array Heap "add-to" %eax)
36963     # convert
36964     c7 0/subop/copy *Curr-block-depth 0/imm32
36965     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
36966     (flush _test-output-buffered-file)
36967 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
36973     # check output
36974     (check-next-stream-line-equal _test-output-stream "81 0/subop/add *(ebp+0x00000008) 0x34/imm32" "F - test-add-literal-to-mem")
36975     # . epilogue
36976     89/<- %esp 5/r32/ebp
36977     5d/pop-to-ebp
36978     c3/return
36979 
36980 test-shift-reg-by-literal:
36981     #   var1/ecx <- shift-left 2
36982     # =>
36983     #   c1/shift 4/subop/left %ecx 2/imm8
36984     #
36985     # . prologue
36986     55/push-ebp
36987     89/<- %ebp 4/r32/esp
36988     # setup
36989     (clear-stream _test-output-stream)
36990     (clear-stream $_test-output-buffered-file->buffer)
36991 $test-shift-reg-by-literal:initialize-var-type:
36992     # var type/ecx: (payload type-tree) = int
36993     68/push 0/imm32/right:null
36994     68/push 0/imm32/right:null
36995     68/push 0/imm32/left:unused
36996     68/push 1/imm32/value:int
36997     68/push 1/imm32/is-atom?:true
36998     68/push 0x11/imm32/alloc-id:fake:payload
36999     89/<- %ecx 4/r32/esp
37000 $test-shift-reg-by-literal:initialize-var:
37001     # var v/ecx: (payload var)
37002     68/push 0/imm32/register
37003     68/push 0/imm32/register
37004     68/push 0/imm32/no-stack-offset
37005     68/push 1/imm32/block-depth
37006     51/push-ecx
37007     68/push 0x11/imm32/alloc-id:fake
37008     68/push 0/imm32/name
37009     68/push 0/imm32/name
37010     68/push 0x11/imm32/alloc-id:fake:payload
37011     89/<- %ecx 4/r32/esp
37012 $test-shift-reg-by-literal:initialize-var-name:
37013     # v->name = "v"
37014     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
37015     (copy-array Heap "v" %eax)
37016 $test-shift-reg-by-literal:initialize-var-register:
37017     # v->register = "ecx"
37018     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
37019     (copy-array Heap "ecx" %eax)
37020 $test-shift-reg-by-literal:initialize-literal-type:
37021     # var type/edx: (payload type-tree) = literal
37022     68/push 0/imm32/right:null
37023     68/push 0/imm32/right:null
37024     68/push 0/imm32/left:unused
37025     68/push 0/imm32/value:literal
37026     68/push 1/imm32/is-atom?:true
37027     68/push 0x11/imm32/alloc-id:fake:payload
37028     89/<- %edx 4/r32/esp
37029 $test-shift-reg-by-literal:initialize-literal:
37030     # var l/edx: (payload var)
37031     68/push 0/imm32/register
37032     68/push 0/imm32/register
37033     68/push 0/imm32/no-stack-offset
37034     68/push 1/imm32/block-depth
37035     52/push-edx
37036     68/push 0x11/imm32/alloc-id:fake
37037     68/push 0/imm32/name
37038     68/push 0/imm32/name
37039     68/push 0x11/imm32/alloc-id:fake:payload
37040     89/<- %edx 4/r32/esp
37041 $test-shift-reg-by-literal:initialize-literal-value:
37042     # l->name = "2"
37043     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
37044     (copy-array Heap "2" %eax)
37045 $test-shift-reg-by-literal:initialize-inouts:
37046     # var inouts/esi: (payload stmt-var) = [l]
37047     68/push 0/imm32/is-deref:false
37048     68/push 0/imm32/next
37049     68/push 0/imm32/next
37050     52/push-edx/l
37051     68/push 0x11/imm32/alloc-id:fake
37052     68/push 0x11/imm32/alloc-id:fake:payload
37053     89/<- %esi 4/r32/esp
37054 $test-shift-reg-by-literal:initialize-outputs:
37055     # var outputs/edi: (payload stmt-var) = [v]
37056     68/push 0/imm32/is-deref:false
37057     68/push 0/imm32/next
37058     68/push 0/imm32/next
37059     51/push-ecx/v
37060     68/push 0x11/imm32/alloc-id:fake
37061     68/push 0x11/imm32/alloc-id:fake:payload
37062     89/<- %edi 4/r32/esp
37063 $test-shift-reg-by-literal:initialize-stmt:
37064     # var stmt/esi: (addr statement)
37065     68/push 0/imm32/next
37066     68/push 0/imm32/next
37067     57/push-edi/outputs
37068     68/push 0x11/imm32/alloc-id:fake
37069     56/push-esi/inouts
37070     68/push 0x11/imm32/alloc-id:fake
37071     68/push 0/imm32/operation
37072     68/push 0/imm32/operation
37073     68/push 1/imm32/tag:stmt1
37074     89/<- %esi 4/r32/esp
37075 $test-shift-reg-by-literal:initialize-stmt-operation:
37076     # stmt->operation = "shift-left"
37077     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
37078     (copy-array Heap "shift-left" %eax)
37079     # convert
37080     c7 0/subop/copy *Curr-block-depth 0/imm32
37081     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
37082     (flush _test-output-buffered-file)
37083 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
37089     # check output
37090     (check-next-stream-line-equal _test-output-stream "c1/shift 4/subop/left %ecx 2/imm8" "F - test-shift-reg-by-literal")
37091     # . epilogue
37092     89/<- %esp 5/r32/ebp
37093     5d/pop-to-ebp
37094     c3/return
37095 
37096 test-shift-mem-by-literal:
37097     #   shift-left var 3
37098     # =>
37099     #   c1/shift 4/subop/left *(ebp+8) 3/imm8
37100     #
37101     # . prologue
37102     55/push-ebp
37103     89/<- %ebp 4/r32/esp
37104     # setup
37105     (clear-stream _test-output-stream)
37106     (clear-stream $_test-output-buffered-file->buffer)
37107 $test-shift-mem-by-literal:initialize-type:
37108     # var type/ecx: (payload type-tree) = int
37109     68/push 0/imm32/right:null
37110     68/push 0/imm32/right:null
37111     68/push 0/imm32/left:unused
37112     68/push 1/imm32/value:int
37113     68/push 1/imm32/is-atom?:true
37114     68/push 0x11/imm32/alloc-id:fake:payload
37115     89/<- %ecx 4/r32/esp
37116 $test-shift-mem-by-literal:initialize-var1:
37117     # var var1/ecx: (payload var)
37118     68/push 0/imm32/register
37119     68/push 0/imm32/register
37120     68/push 8/imm32/stack-offset
37121     68/push 1/imm32/block-depth
37122     51/push-ecx
37123     68/push 0x11/imm32/alloc-id:fake
37124     68/push 0/imm32/name
37125     68/push 0/imm32/name
37126     68/push 0x11/imm32/alloc-id:fake:payload
37127     89/<- %ecx 4/r32/esp
37128 $test-shift-mem-by-literal:initialize-var1-name:
37129     # var1->name = "var1"
37130     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
37131     (copy-array Heap "var1" %eax)
37132 $test-shift-mem-by-literal:initialize-literal-type:
37133     # var type/edx: (payload type-tree) = literal
37134     68/push 0/imm32/right:null
37135     68/push 0/imm32/right:null
37136     68/push 0/imm32/left:unused
37137     68/push 0/imm32/value:literal
37138     68/push 1/imm32/is-atom?:true
37139     68/push 0x11/imm32/alloc-id:fake:payload
37140     89/<- %edx 4/r32/esp
37141 $test-shift-mem-by-literal:initialize-literal:
37142     # var l/edx: (payload var)
37143     68/push 0/imm32/register
37144     68/push 0/imm32/register
37145     68/push 0/imm32/no-stack-offset
37146     68/push 1/imm32/block-depth
37147     52/push-edx
37148     68/push 0x11/imm32/alloc-id:fake
37149     68/push 0/imm32/name
37150     68/push 0/imm32/name
37151     68/push 0x11/imm32/alloc-id:fake:payload
37152     89/<- %edx 4/r32/esp
37153 $test-shift-mem-by-literal:initialize-literal-value:
37154     # l->name = "3"
37155     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
37156     (copy-array Heap "3" %eax)
37157 $test-shift-mem-by-literal:initialize-inouts:
37158     # var inouts/esi: (payload stmt-var) = [l]
37159     68/push 0/imm32/is-deref:false
37160     68/push 0/imm32/next
37161     68/push 0/imm32/next
37162     52/push-edx/l
37163     68/push 0x11/imm32/alloc-id:fake
37164     68/push 0x11/imm32/alloc-id:fake:payload
37165     89/<- %esi 4/r32/esp
37166     # var inouts = (handle stmt-var) = [var1, var2]
37167     68/push 0/imm32/is-deref:false
37168     56/push-esi/next
37169     68/push 0x11/imm32/alloc-id:fake
37170     51/push-ecx/var1
37171     68/push 0x11/imm32/alloc-id:fake
37172     68/push 0x11/imm32/alloc-id:fake:payload
37173     89/<- %esi 4/r32/esp
37174 $test-shift-mem-by-literal:initialize-stmt:
37175     # var stmt/esi: (addr statement)
37176     68/push 0/imm32/next
37177     68/push 0/imm32/next
37178     68/push 0/imm32/outputs
37179     68/push 0/imm32/outputs
37180     56/push-esi/inouts
37181     68/push 0x11/imm32/alloc-id:fake
37182     68/push 0/imm32/operation
37183     68/push 0/imm32/operation
37184     68/push 1/imm32/tag:stmt1
37185     89/<- %esi 4/r32/esp
37186 $test-shift-mem-by-literal:initialize-stmt-operation:
37187     # stmt->operation = "shift-left"
37188     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
37189     (copy-array Heap "shift-left" %eax)
37190     # convert
37191     c7 0/subop/copy *Curr-block-depth 0/imm32
37192     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
37193     (flush _test-output-buffered-file)
37194 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
37200     # check output
37201     (check-next-stream-line-equal _test-output-stream "c1/shift 4/subop/left *(ebp+0x00000008) 3/imm8" "F - test-shift-mem-by-literal")
37202     # . epilogue
37203     89/<- %esp 5/r32/ebp
37204     5d/pop-to-ebp
37205     c3/return
37206 
37207 test-compare-reg-with-reg:
37208     #   compare var1/ecx, var2/eax
37209     # =>
37210     #   39/compare %ecx 0/r32/eax
37211     #
37212     # . prologue
37213     55/push-ebp
37214     89/<- %ebp 4/r32/esp
37215     # setup
37216     (clear-stream _test-output-stream)
37217     (clear-stream $_test-output-buffered-file->buffer)
37218 $test-compare-reg-with-reg:initialize-type:
37219     # var type/ecx: (payload type-tree) = int
37220     68/push 0/imm32/right:null
37221     68/push 0/imm32/right:null
37222     68/push 0/imm32/left:unused
37223     68/push 1/imm32/value:int
37224     68/push 1/imm32/is-atom?:true
37225     68/push 0x11/imm32/alloc-id:fake:payload
37226     89/<- %ecx 4/r32/esp
37227 $test-compare-reg-with-reg:initialize-var1:
37228     # var var1/ecx: (payload var)
37229     68/push 0/imm32/register
37230     68/push 0/imm32/register
37231     68/push 0/imm32/no-stack-offset
37232     68/push 1/imm32/block-depth
37233     51/push-ecx
37234     68/push 0x11/imm32/alloc-id:fake
37235     68/push 0/imm32/name
37236     68/push 0/imm32/name
37237     68/push 0x11/imm32/alloc-id:fake:payload
37238     89/<- %ecx 4/r32/esp
37239 $test-compare-reg-with-reg:initialize-var1-name:
37240     # var1->name = "var1"
37241     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
37242     (copy-array Heap "var1" %eax)
37243 $test-compare-reg-with-reg:initialize-var1-register:
37244     # var1->register = "ecx"
37245     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
37246     (copy-array Heap "ecx" %eax)
37247 $test-compare-reg-with-reg:initialize-var2:
37248     # var var2/edx: (payload var)
37249     68/push 0/imm32/register
37250     68/push 0/imm32/register
37251     68/push 0/imm32/no-stack-offset
37252     68/push 1/imm32/block-depth
37253     ff 6/subop/push *(ecx+0x10)
37254     68/push 0x11/imm32/alloc-id:fake
37255     68/push 0/imm32/name
37256     68/push 0/imm32/name
37257     68/push 0x11/imm32/alloc-id:fake:payload
37258     89/<- %edx 4/r32/esp
37259 $test-compare-reg-with-reg:initialize-var2-name:
37260     # var2->name = "var2"
37261     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
37262     (copy-array Heap "var2" %eax)
37263 $test-compare-reg-with-reg:initialize-var2-register:
37264     # var2->register = "eax"
37265     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
37266     (copy-array Heap "eax" %eax)
37267 $test-compare-reg-with-reg:initialize-inouts:
37268     # var inouts/esi: (payload stmt-var) = [var2]
37269     68/push 0/imm32/is-deref:false
37270     68/push 0/imm32/next
37271     68/push 0/imm32/next
37272     52/push-edx/var2
37273     68/push 0x11/imm32/alloc-id:fake
37274     68/push 0x11/imm32/alloc-id:fake:payload
37275     89/<- %esi 4/r32/esp
37276     # inouts = [var1, var2]
37277     68/push 0/imm32/is-deref:false
37278     56/push-esi/next
37279     68/push 0x11/imm32/alloc-id:fake
37280     51/push-ecx/var1
37281     68/push 0x11/imm32/alloc-id:fake
37282     68/push 0x11/imm32/alloc-id:fake:payload
37283     89/<- %esi 4/r32/esp
37284 $test-compare-reg-with-reg:initialize-stmt:
37285     # var stmt/esi: (addr statement)
37286     68/push 0/imm32/next
37287     68/push 0/imm32/next
37288     68/push 0/imm32/outputs
37289     68/push 0/imm32/outputs
37290     56/push-esi/inouts
37291     68/push 0x11/imm32/alloc-id:fake
37292     68/push 0/imm32/operation
37293     68/push 0/imm32/operation
37294     68/push 1/imm32/tag:stmt1
37295     89/<- %esi 4/r32/esp
37296 $test-compare-reg-with-reg:initialize-stmt-operation:
37297     # stmt->operation = "compare"
37298     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
37299     (copy-array Heap "compare" %eax)
37300     # convert
37301     c7 0/subop/copy *Curr-block-depth 0/imm32
37302     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
37303     (flush _test-output-buffered-file)
37304 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
37310     # check output
37311     (check-next-stream-line-equal _test-output-stream "39/compare-> %ecx 0x00000000/r32" "F - test-compare-reg-with-reg")
37312     # . epilogue
37313     89/<- %esp 5/r32/ebp
37314     5d/pop-to-ebp
37315     c3/return
37316 
37317 test-compare-mem-with-reg:
37318     #   compare var1, var2/eax
37319     # =>
37320     #   39/compare *(ebp+___) 0/r32/eax
37321     #
37322     # . prologue
37323     55/push-ebp
37324     89/<- %ebp 4/r32/esp
37325     # setup
37326     (clear-stream _test-output-stream)
37327     (clear-stream $_test-output-buffered-file->buffer)
37328 $test-compare-mem-with-reg:initialize-type:
37329     # var type/ecx: (payload type-tree) = int
37330     68/push 0/imm32/right:null
37331     68/push 0/imm32/right:null
37332     68/push 0/imm32/left:unused
37333     68/push 1/imm32/value:int
37334     68/push 1/imm32/is-atom?:true
37335     68/push 0x11/imm32/alloc-id:fake:payload
37336     89/<- %ecx 4/r32/esp
37337 $test-compare-mem-with-reg:initialize-var1:
37338     # var var1/ecx: (payload var)
37339     68/push 0/imm32/register
37340     68/push 0/imm32/register
37341     68/push 8/imm32/stack-offset
37342     68/push 1/imm32/block-depth
37343     51/push-ecx
37344     68/push 0x11/imm32/alloc-id:fake
37345     68/push 0/imm32/name
37346     68/push 0/imm32/name
37347     68/push 0x11/imm32/alloc-id:fake:payload
37348     89/<- %ecx 4/r32/esp
37349 $test-compare-mem-with-reg:initialize-var1-name:
37350     # var1->name = "var1"
37351     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
37352     (copy-array Heap "var1" %eax)
37353 $test-compare-mem-with-reg:initialize-var2:
37354     # var var2/edx: (payload var)
37355     68/push 0/imm32/register
37356     68/push 0/imm32/register
37357     68/push 0/imm32/no-stack-offset
37358     68/push 1/imm32/block-depth
37359     ff 6/subop/push *(ecx+0x10)
37360     68/push 0x11/imm32/alloc-id:fake
37361     68/push 0/imm32/name
37362     68/push 0/imm32/name
37363     68/push 0x11/imm32/alloc-id:fake:payload
37364     89/<- %edx 4/r32/esp
37365 $test-compare-mem-with-reg:initialize-var2-name:
37366     # var2->name = "var2"
37367     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
37368     (copy-array Heap "var2" %eax)
37369 $test-compare-mem-with-reg:initialize-var2-register:
37370     # var2->register = "eax"
37371     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
37372     (copy-array Heap "eax" %eax)
37373 $test-compare-mem-with-reg:initialize-inouts:
37374     # var inouts/esi: (payload stmt-var) = [var2]
37375     68/push 0/imm32/is-deref:false
37376     68/push 0/imm32/next
37377     68/push 0/imm32/next
37378     52/push-edx/var2
37379     68/push 0x11/imm32/alloc-id:fake
37380     68/push 0x11/imm32/alloc-id:fake:payload
37381     89/<- %esi 4/r32/esp
37382     # inouts = [var1, var2]
37383     68/push 0/imm32/is-deref:false
37384     56/push-esi/next
37385     68/push 0x11/imm32/alloc-id:fake
37386     51/push-ecx/var1
37387     68/push 0x11/imm32/alloc-id:fake
37388     68/push 0x11/imm32/alloc-id:fake:payload
37389     89/<- %esi 4/r32/esp
37390 $test-compare-mem-with-reg:initialize-stmt:
37391     # var stmt/esi: (addr statement)
37392     68/push 0/imm32/next
37393     68/push 0/imm32/next
37394     68/push 0/imm32/outputs
37395     68/push 0/imm32/outputs
37396     56/push-esi/inouts
37397     68/push 0x11/imm32/alloc-id:fake
37398     68/push 0/imm32/operation
37399     68/push 0/imm32/operation
37400     68/push 1/imm32/tag:stmt1
37401     89/<- %esi 4/r32/esp
37402 $test-compare-mem-with-reg:initialize-stmt-operation:
37403     # stmt->operation = "compare"
37404     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
37405     (copy-array Heap "compare" %eax)
37406     # convert
37407     c7 0/subop/copy *Curr-block-depth 0/imm32
37408     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
37409     (flush _test-output-buffered-file)
37410 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
37416     # check output
37417     (check-next-stream-line-equal _test-output-stream "39/compare-> *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-mem-with-reg")
37418     # . epilogue
37419     89/<- %esp 5/r32/ebp
37420     5d/pop-to-ebp
37421     c3/return
37422 
37423 test-compare-reg-with-mem:
37424     #   compare var1/eax, var2
37425     # =>
37426     #   3b/compare<- *(ebp+___) 0/r32/eax
37427     #
37428     # . prologue
37429     55/push-ebp
37430     89/<- %ebp 4/r32/esp
37431     # setup
37432     (clear-stream _test-output-stream)
37433     (clear-stream $_test-output-buffered-file->buffer)
37434 $test-compare-reg-with-mem:initialize-type:
37435     # var type/ecx: (payload type-tree) = int
37436     68/push 0/imm32/right:null
37437     68/push 0/imm32/right:null
37438     68/push 0/imm32/left:unused
37439     68/push 1/imm32/value:int
37440     68/push 1/imm32/is-atom?:true
37441     68/push 0x11/imm32/alloc-id:fake:payload
37442     89/<- %ecx 4/r32/esp
37443 $test-compare-reg-with-mem:initialize-var1:
37444     # var var1/ecx: (payload var)
37445     68/push 0/imm32/register
37446     68/push 0/imm32/register
37447     68/push 0/imm32/no-stack-offset
37448     68/push 1/imm32/block-depth
37449     51/push-ecx
37450     68/push 0x11/imm32/alloc-id:fake
37451     68/push 0/imm32/name
37452     68/push 0/imm32/name
37453     68/push 0x11/imm32/alloc-id:fake:payload
37454     89/<- %ecx 4/r32/esp
37455 $test-compare-reg-with-mem:initialize-var1-name:
37456     # var1->name = "var1"
37457     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
37458     (copy-array Heap "var1" %eax)
37459 $test-compare-reg-with-mem:initialize-var1-register:
37460     # var1->register = "eax"
37461     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
37462     (copy-array Heap "eax" %eax)
37463 $test-compare-reg-with-mem:initialize-var2:
37464     # var var2/edx: (payload var)
37465     68/push 0/imm32/register
37466     68/push 0/imm32/register
37467     68/push 8/imm32/stack-offset
37468     68/push 1/imm32/block-depth
37469     ff 6/subop/push *(ecx+0x10)
37470     68/push 0x11/imm32/alloc-id:fake
37471     68/push 0/imm32/name
37472     68/push 0/imm32/name
37473     68/push 0x11/imm32/alloc-id:fake:payload
37474     89/<- %edx 4/r32/esp
37475 $test-compare-reg-with-mem:initialize-var2-name:
37476     # var2->name = "var2"
37477     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
37478     (copy-array Heap "var2" %eax)
37479 $test-compare-reg-with-mem:initialize-inouts:
37480     # var inouts/esi: (payload stmt-var) = [var2]
37481     68/push 0/imm32/is-deref:false
37482     68/push 0/imm32/next
37483     68/push 0/imm32/next
37484     52/push-edx/var2
37485     68/push 0x11/imm32/alloc-id:fake
37486     68/push 0x11/imm32/alloc-id:fake:payload
37487     89/<- %esi 4/r32/esp
37488     # inouts = [var1, var2]
37489     68/push 0/imm32/is-deref:false
37490     56/push-esi/next
37491     68/push 0x11/imm32/alloc-id:fake
37492     51/push-ecx/var1
37493     68/push 0x11/imm32/alloc-id:fake
37494     68/push 0x11/imm32/alloc-id:fake:payload
37495     89/<- %esi 4/r32/esp
37496 $test-compare-reg-with-mem:initialize-stmt:
37497     # var stmt/esi: (addr statement)
37498     68/push 0/imm32/next
37499     68/push 0/imm32/next
37500     68/push 0/imm32/outputs
37501     68/push 0/imm32/outputs
37502     56/push-esi/inouts
37503     68/push 0x11/imm32/alloc-id:fake
37504     68/push 0/imm32/operation
37505     68/push 0/imm32/operation
37506     68/push 1/imm32/tag:stmt1
37507     89/<- %esi 4/r32/esp
37508 $test-compare-reg-with-mem:initialize-stmt-operation:
37509     # stmt->operation = "compare"
37510     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
37511     (copy-array Heap "compare" %eax)
37512     # convert
37513     c7 0/subop/copy *Curr-block-depth 0/imm32
37514     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
37515     (flush _test-output-buffered-file)
37516 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
37522     # check output
37523     (check-next-stream-line-equal _test-output-stream "3b/compare<- *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-reg-with-mem")
37524     # . epilogue
37525     89/<- %esp 5/r32/ebp
37526     5d/pop-to-ebp
37527     c3/return
37528 
37529 test-compare-mem-with-literal:
37530     #   compare var1, 0x34
37531     # =>
37532     #   81 7/subop/compare *(ebp+___) 0x34/imm32
37533     #
37534     # . prologue
37535     55/push-ebp
37536     89/<- %ebp 4/r32/esp
37537     # setup
37538     (clear-stream _test-output-stream)
37539     (clear-stream $_test-output-buffered-file->buffer)
37540 $test-compare-mem-with-literal:initialize-type:
37541     # var type/ecx: (payload type-tree) = int
37542     68/push 0/imm32/right:null
37543     68/push 0/imm32/right:null
37544     68/push 0/imm32/left:unused
37545     68/push 1/imm32/value:int
37546     68/push 1/imm32/is-atom?:true
37547     68/push 0x11/imm32/alloc-id:fake:payload
37548     89/<- %ecx 4/r32/esp
37549 $test-compare-mem-with-literal:initialize-var1:
37550     # var var1/ecx: (payload var)
37551     68/push 0/imm32/register
37552     68/push 0/imm32/register
37553     68/push 8/imm32/stack-offset
37554     68/push 1/imm32/block-depth
37555     51/push-ecx
37556     68/push 0x11/imm32/alloc-id:fake
37557     68/push 0/imm32/name
37558     68/push 0/imm32/name
37559     68/push 0x11/imm32/alloc-id:fake:payload
37560     89/<- %ecx 4/r32/esp
37561 $test-compare-mem-with-literal:initialize-var1-name:
37562     # var1->name = "var1"
37563     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
37564     (copy-array Heap "var1" %eax)
37565 $test-compare-mem-with-literal:initialize-literal-type:
37566     # var type/edx: (payload type-tree) = literal
37567     68/push 0/imm32/right:null
37568     68/push 0/imm32/right:null
37569     68/push 0/imm32/left:unused
37570     68/push 0/imm32/value:literal
37571     68/push 1/imm32/is-atom?:true
37572     68/push 0x11/imm32/alloc-id:fake:payload
37573     89/<- %edx 4/r32/esp
37574 $test-compare-mem-with-literal:initialize-literal:
37575     # var l/edx: (payload var)
37576     68/push 0/imm32/register
37577     68/push 0/imm32/register
37578     68/push 0/imm32/no-stack-offset
37579     68/push 1/imm32/block-depth
37580     52/push-edx
37581     68/push 0x11/imm32/alloc-id:fake
37582     68/push 0/imm32/name
37583     68/push 0/imm32/name
37584     68/push 0x11/imm32/alloc-id:fake:payload
37585     89/<- %edx 4/r32/esp
37586 $test-compare-mem-with-literal:initialize-literal-value:
37587     # l->name = "0x34"
37588     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
37589     (copy-array Heap "0x34" %eax)
37590 $test-compare-mem-with-literal:initialize-inouts:
37591     # var inouts/esi: (payload stmt-var) = [l]
37592     68/push 0/imm32/is-deref:false
37593     68/push 0/imm32/next
37594     68/push 0/imm32/next
37595     52/push-edx/l
37596     68/push 0x11/imm32/alloc-id:fake
37597     68/push 0x11/imm32/alloc-id:fake:payload
37598     89/<- %esi 4/r32/esp
37599     # var inouts = (handle stmt-var) = [var1, var2]
37600     68/push 0/imm32/is-deref:false
37601     56/push-esi/next
37602     68/push 0x11/imm32/alloc-id:fake
37603     51/push-ecx/var1
37604     68/push 0x11/imm32/alloc-id:fake
37605     68/push 0x11/imm32/alloc-id:fake:payload
37606     89/<- %esi 4/r32/esp
37607 $test-compare-mem-with-literal:initialize-stmt:
37608     # var stmt/esi: (addr statement)
37609     68/push 0/imm32/next
37610     68/push 0/imm32/next
37611     68/push 0/imm32/outputs
37612     68/push 0/imm32/outputs
37613     56/push-esi/inouts
37614     68/push 0x11/imm32/alloc-id:fake
37615     68/push 0/imm32/operation
37616     68/push 0/imm32/operation
37617     68/push 1/imm32/tag:stmt1
37618     89/<- %esi 4/r32/esp
37619 $test-compare-mem-with-literal:initialize-stmt-operation:
37620     # stmt->operation = "compare"
37621     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
37622     (copy-array Heap "compare" %eax)
37623     # convert
37624     c7 0/subop/copy *Curr-block-depth 0/imm32
37625     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
37626     (flush _test-output-buffered-file)
37627 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
37633     # check output
37634     (check-next-stream-line-equal _test-output-stream "81 7/subop/compare *(ebp+0x00000008) 0x34/imm32" "F - test-compare-mem-with-literal")
37635     # . epilogue
37636     89/<- %esp 5/r32/ebp
37637     5d/pop-to-ebp
37638     c3/return
37639 
37640 test-compare-eax-with-literal:
37641     #   compare var1/eax 0x34
37642     # =>
37643     #   3d/compare-eax-with 0x34/imm32
37644     #
37645     # . prologue
37646     55/push-ebp
37647     89/<- %ebp 4/r32/esp
37648     # setup
37649     (clear-stream _test-output-stream)
37650     (clear-stream $_test-output-buffered-file->buffer)
37651 $test-compare-eax-with-literal:initialize-type:
37652     # var type/ecx: (payload type-tree) = int
37653     68/push 0/imm32/right:null
37654     68/push 0/imm32/right:null
37655     68/push 0/imm32/left:unused
37656     68/push 1/imm32/value:int
37657     68/push 1/imm32/is-atom?:true
37658     68/push 0x11/imm32/alloc-id:fake:payload
37659     89/<- %ecx 4/r32/esp
37660 $test-compare-eax-with-literal:initialize-var1:
37661     # var var1/ecx: (payload var)
37662     68/push 0/imm32/register
37663     68/push 0/imm32/register
37664     68/push 0/imm32/no-stack-offset
37665     68/push 1/imm32/block-depth
37666     51/push-ecx
37667     68/push 0x11/imm32/alloc-id:fake
37668     68/push 0/imm32/name
37669     68/push 0/imm32/name
37670     68/push 0x11/imm32/alloc-id:fake:payload
37671     89/<- %ecx 4/r32/esp
37672 $test-compare-eax-with-literal:initialize-var1-name:
37673     # var1->name = "var1"
37674     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
37675     (copy-array Heap "var1" %eax)
37676 $test-compare-eax-with-literal:initialize-var1-register:
37677     # v->register = "eax"
37678     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
37679     (copy-array Heap "eax" %eax)
37680 $test-compare-eax-with-literal:initialize-literal-type:
37681     # var type/edx: (payload type-tree) = literal
37682     68/push 0/imm32/right:null
37683     68/push 0/imm32/right:null
37684     68/push 0/imm32/left:unused
37685     68/push 0/imm32/value:literal
37686     68/push 1/imm32/is-atom?:true
37687     68/push 0x11/imm32/alloc-id:fake:payload
37688     89/<- %edx 4/r32/esp
37689 $test-compare-eax-with-literal:initialize-literal:
37690     # var l/edx: (payload var)
37691     68/push 0/imm32/register
37692     68/push 0/imm32/register
37693     68/push 0/imm32/no-stack-offset
37694     68/push 1/imm32/block-depth
37695     52/push-edx
37696     68/push 0x11/imm32/alloc-id:fake
37697     68/push 0/imm32/name
37698     68/push 0/imm32/name
37699     68/push 0x11/imm32/alloc-id:fake:payload
37700     89/<- %edx 4/r32/esp
37701 $test-compare-eax-with-literal:initialize-literal-value:
37702     # l->name = "0x34"
37703     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
37704     (copy-array Heap "0x34" %eax)
37705 $test-compare-eax-with-literal:initialize-inouts:
37706     # var inouts/esi: (payload stmt-var) = [l]
37707     68/push 0/imm32/is-deref:false
37708     68/push 0/imm32/next
37709     68/push 0/imm32/next
37710     52/push-edx/l
37711     68/push 0x11/imm32/alloc-id:fake
37712     68/push 0x11/imm32/alloc-id:fake:payload
37713     89/<- %esi 4/r32/esp
37714     # var inouts = (handle stmt-var) = [var1, var2]
37715     68/push 0/imm32/is-deref:false
37716     56/push-esi/next
37717     68/push 0x11/imm32/alloc-id:fake
37718     51/push-ecx/var1
37719     68/push 0x11/imm32/alloc-id:fake
37720     68/push 0x11/imm32/alloc-id:fake:payload
37721     89/<- %esi 4/r32/esp
37722 $test-compare-eax-with-literal:initialize-stmt:
37723     # var stmt/esi: (addr statement)
37724     68/push 0/imm32/next
37725     68/push 0/imm32/next
37726     68/push 0/imm32/outputs
37727     68/push 0/imm32/outputs
37728     56/push-esi/inouts
37729     68/push 0x11/imm32/alloc-id:fake
37730     68/push 0/imm32/operation
37731     68/push 0/imm32/operation
37732     68/push 1/imm32/tag:stmt1
37733     89/<- %esi 4/r32/esp
37734 $test-compare-eax-with-literal:initialize-stmt-operation:
37735     # stmt->operation = "compare"
37736     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
37737     (copy-array Heap "compare" %eax)
37738     # convert
37739     c7 0/subop/copy *Curr-block-depth 0/imm32
37740     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
37741     (flush _test-output-buffered-file)
37742 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
37748     # check output
37749     (check-next-stream-line-equal _test-output-stream "3d/compare-eax-with 0x34/imm32" "F - test-compare-eax-with-literal")
37750     # . epilogue
37751     89/<- %esp 5/r32/ebp
37752     5d/pop-to-ebp
37753     c3/return
37754 
37755 test-compare-reg-with-literal:
37756     #   compare var1/ecx 0x34
37757     # =>
37758     #   81 7/subop/compare %ecx 0x34/imm32
37759     #
37760     # . prologue
37761     55/push-ebp
37762     89/<- %ebp 4/r32/esp
37763     # setup
37764     (clear-stream _test-output-stream)
37765     (clear-stream $_test-output-buffered-file->buffer)
37766 $test-compare-reg-with-literal:initialize-type:
37767     # var type/ecx: (payload type-tree) = int
37768     68/push 0/imm32/right:null
37769     68/push 0/imm32/right:null
37770     68/push 0/imm32/left:unused
37771     68/push 1/imm32/value:int
37772     68/push 1/imm32/is-atom?:true
37773     68/push 0x11/imm32/alloc-id:fake:payload
37774     89/<- %ecx 4/r32/esp
37775 $test-compare-reg-with-literal:initialize-var1:
37776     # var var1/ecx: (payload var)
37777     68/push 0/imm32/register
37778     68/push 0/imm32/register
37779     68/push 0/imm32/no-stack-offset
37780     68/push 1/imm32/block-depth
37781     51/push-ecx
37782     68/push 0x11/imm32/alloc-id:fake
37783     68/push 0/imm32/name
37784     68/push 0/imm32/name
37785     68/push 0x11/imm32/alloc-id:fake:payload
37786     89/<- %ecx 4/r32/esp
37787 $test-compare-reg-with-literal:initialize-var1-name:
37788     # var1->name = "var1"
37789     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
37790     (copy-array Heap "var1" %eax)
37791 $test-compare-reg-with-literal:initialize-var1-register:
37792     # v->register = "ecx"
37793     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
37794     (copy-array Heap "ecx" %eax)
37795 $test-compare-reg-with-literal:initialize-literal-type:
37796     # var type/edx: (payload type-tree) = literal
37797     68/push 0/imm32/right:null
37798     68/push 0/imm32/right:null
37799     68/push 0/imm32/left:unused
37800     68/push 0/imm32/value:literal
37801     68/push 1/imm32/is-atom?:true
37802     68/push 0x11/imm32/alloc-id:fake:payload
37803     89/<- %edx 4/r32/esp
37804 $test-compare-reg-with-literal:initialize-literal:
37805     # var l/edx: (payload var)
37806     68/push 0/imm32/register
37807     68/push 0/imm32/register
37808     68/push 0/imm32/no-stack-offset
37809     68/push 1/imm32/block-depth
37810     52/push-edx
37811     68/push 0x11/imm32/alloc-id:fake
37812     68/push 0/imm32/name
37813     68/push 0/imm32/name
37814     68/push 0x11/imm32/alloc-id:fake:payload
37815     89/<- %edx 4/r32/esp
37816 $test-compare-reg-with-literal:initialize-literal-value:
37817     # l->name = "0x34"
37818     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
37819     (copy-array Heap "0x34" %eax)
37820 $test-compare-reg-with-literal:initialize-inouts:
37821     # var inouts/esi: (payload stmt-var) = [l]
37822     68/push 0/imm32/is-deref:false
37823     68/push 0/imm32/next
37824     68/push 0/imm32/next
37825     52/push-edx/l
37826     68/push 0x11/imm32/alloc-id:fake
37827     68/push 0x11/imm32/alloc-id:fake:payload
37828     89/<- %esi 4/r32/esp
37829     # var inouts = (handle stmt-var) = [var1, var2]
37830     68/push 0/imm32/is-deref:false
37831     56/push-esi/next
37832     68/push 0x11/imm32/alloc-id:fake
37833     51/push-ecx/var1
37834     68/push 0x11/imm32/alloc-id:fake
37835     68/push 0x11/imm32/alloc-id:fake:payload
37836     89/<- %esi 4/r32/esp
37837 $test-compare-reg-with-literal:initialize-stmt:
37838     # var stmt/esi: (addr statement)
37839     68/push 0/imm32/next
37840     68/push 0/imm32/next
37841     68/push 0/imm32/outputs
37842     68/push 0/imm32/outputs
37843     56/push-esi/inouts
37844     68/push 0x11/imm32/alloc-id:fake
37845     68/push 0/imm32/operation
37846     68/push 0/imm32/operation
37847     68/push 1/imm32/tag:stmt1
37848     89/<- %esi 4/r32/esp
37849 $test-compare-reg-with-literal:initialize-stmt-operation:
37850     # stmt->operation = "compare"
37851     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
37852     (copy-array Heap "compare" %eax)
37853     # convert
37854     c7 0/subop/copy *Curr-block-depth 0/imm32
37855     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
37856     (flush _test-output-buffered-file)
37857 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
37863     # check output
37864     (check-next-stream-line-equal _test-output-stream "81 7/subop/compare %ecx 0x34/imm32" "F - test-compare-reg-with-literal")
37865     # . epilogue
37866     89/<- %esp 5/r32/ebp
37867     5d/pop-to-ebp
37868     c3/return
37869 
37870 test-emit-subx-stmt-function-call:
37871     # Call a function on a variable on the stack.
37872     #   f foo
37873     # =>
37874     #   (f *(ebp-8))
37875     # (Changing the function name supports overloading in general, but here it
37876     # just serves to help disambiguate things.)
37877     #
37878     # There's a variable on the var stack as follows:
37879     #   name: 'foo'
37880     #   type: int
37881     #   stack-offset: -8
37882     #
37883     # There's nothing in primitives.
37884     #
37885     # We don't perform any checking here on the type of 'f'.
37886     #
37887     # . prologue
37888     55/push-ebp
37889     89/<- %ebp 4/r32/esp
37890     # setup
37891     (clear-stream _test-output-stream)
37892     (clear-stream $_test-output-buffered-file->buffer)
37893 $test-emit-subx-function-call:initialize-type:
37894     # var type/ecx: (payload type-tree) = int
37895     68/push 0/imm32/right:null
37896     68/push 0/imm32/right:null
37897     68/push 0/imm32/left:unused
37898     68/push 1/imm32/value:int
37899     68/push 1/imm32/is-atom?:true
37900     68/push 0x11/imm32/alloc-id:fake:payload
37901     89/<- %ecx 4/r32/esp
37902 $test-emit-subx-function-call:initialize-var:
37903     # var var-foo/ecx: (payload var) = var(type)
37904     68/push 0/imm32/no-register
37905     68/push 0/imm32/no-register
37906     68/push -8/imm32/stack-offset
37907     68/push 1/imm32/block-depth
37908     51/push-ecx/type
37909     68/push 0x11/imm32/alloc-id:fake
37910     68/push 0/imm32/name
37911     68/push 0/imm32/name
37912     68/push 0x11/imm32/alloc-id:fake:payload
37913     89/<- %ecx 4/r32/esp
37914 $test-emit-subx-function-call:initialize-var-name:
37915     # var-foo->name = "foo"
37916     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
37917     (copy-array Heap "foo" %eax)
37918 $test-emit-subx-function-call:initialize-stmt-var:
37919     # var operand/ebx: (payload stmt-var) = stmt-var(var-foo)
37920     68/push 0/imm32/is-deref:false
37921     68/push 0/imm32/next
37922     68/push 0/imm32/next
37923     51/push-ecx/var-foo
37924     68/push 0x11/imm32/alloc-id:fake
37925     68/push 0x11/imm32/alloc-id:fake:payload
37926     89/<- %ebx 4/r32/esp
37927 $test-emit-subx-function-call:initialize-stmt:
37928     # var stmt/esi: (addr statement)
37929     68/push 0/imm32/no-outputs
37930     68/push 0/imm32/no-outputs
37931     53/push-ebx/inouts
37932     68/push 0x11/imm32/alloc-id:fake
37933     68/push 0/imm32/operation
37934     68/push 0/imm32/operation
37935     68/push 1/imm32/tag
37936     89/<- %esi 4/r32/esp
37937 $test-emit-subx-function-call:initialize-stmt-operation:
37938     # stmt->operation = "f"
37939     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
37940     (copy-array Heap "f" %eax)
37941     # convert
37942     c7 0/subop/copy *Curr-block-depth 0/imm32
37943     (emit-subx-stmt _test-output-buffered-file %esi 0 0 Stderr 0)
37944     (flush _test-output-buffered-file)
37945 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
37951     # check output
37952     (check-next-stream-line-equal _test-output-stream "(f *(ebp+0xfffffff8))" "F - test-emit-subx-stmt-function-call")
37953     # . epilogue
37954     89/<- %esp 5/r32/ebp
37955     5d/pop-to-ebp
37956     c3/return
37957 
37958 test-emit-subx-stmt-function-call-with-literal-arg:
37959     # Call a function on a literal.
37960     #   f 0x34
37961     # =>
37962     #   (f2 0x34)
37963     #
37964     # . prologue
37965     55/push-ebp
37966     89/<- %ebp 4/r32/esp
37967     # setup
37968     (clear-stream _test-output-stream)
37969     (clear-stream $_test-output-buffered-file->buffer)
37970 $test-emit-subx-function-call-with-literal-arg:initialize-type:
37971     # var type/ecx: (payload type-tree) = int
37972     68/push 0/imm32/right:null
37973     68/push 0/imm32/right:null
37974     68/push 0/imm32/left:unused
37975     68/push 0/imm32/value:literal
37976     68/push 1/imm32/is-atom?:true
37977     68/push 0x11/imm32/alloc-id:fake:payload
37978     89/<- %ecx 4/r32/esp
37979 $test-emit-subx-function-call-with-literal-arg:initialize-var:
37980     # var var-foo/ecx: (payload var) = var(lit)
37981     68/push 0/imm32/no-register
37982     68/push 0/imm32/no-register
37983     68/push 0/imm32/no-stack-offset
37984     68/push 1/imm32/block-depth
37985     51/push-ecx/type
37986     68/push 0x11/imm32/alloc-id:fake
37987     68/push 0/imm32/name
37988     68/push 0/imm32/name
37989     68/push 0x11/imm32/alloc-id:fake:payload
37990     89/<- %ecx 4/r32/esp
37991 $test-emit-subx-function-call-with-literal-arg:initialize-var-name:
37992     # var-foo->name = "0x34"
37993     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
37994     (copy-array Heap "0x34" %eax)
37995 $test-emit-subx-function-call-with-literal-arg:initialize-stmt-var:
37996     # var operand/ebx: (payload stmt-var) = stmt-var(var-foo)
37997     68/push 0/imm32/is-deref:false
37998     68/push 0/imm32/next
37999     68/push 0/imm32/next
38000     51/push-ecx/var-foo
38001     68/push 0x11/imm32/alloc-id:fake
38002     68/push 0x11/imm32/alloc-id:fake:payload
38003     89/<- %ebx 4/r32/esp
38004 $test-emit-subx-function-call-with-literal-arg:initialize-stmt:
38005     # var stmt/esi: (addr statement)
38006     68/push 0/imm32/no-outputs
38007     68/push 0/imm32/no-outputs
38008     53/push-ebx/inouts
38009     68/push 0x11/imm32/alloc-id:fake
38010     68/push 0/imm32/operation
38011     68/push 0/imm32/operation
38012     68/push 1/imm32/tag
38013     89/<- %esi 4/r32/esp
38014 $test-emit-subx-function-call-with-literal-arg:initialize-stmt-operation:
38015     # stmt->operation = "f"
38016     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
38017     (copy-array Heap "f" %eax)
38018     # convert
38019     c7 0/subop/copy *Curr-block-depth 0/imm32
38020     (emit-subx-stmt _test-output-buffered-file %esi 0 %ebx 0 Stderr 0)
38021     (flush _test-output-buffered-file)
38022 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
38028     # check output
38029     (check-next-stream-line-equal _test-output-stream "(f 0x34)" "F - test-emit-subx-stmt-function-call-with-literal-arg")
38030     # . epilogue
38031     89/<- %esp 5/r32/ebp
38032     5d/pop-to-ebp
38033     c3/return
38034 
38035 emit-indent:  # out: (addr buffered-file), n: int
38036     # . prologue
38037     55/push-ebp
38038     89/<- %ebp 4/r32/esp
38039     # . save registers
38040     50/push-eax
38041     # var i/eax: int = n
38042     8b/-> *(ebp+0xc) 0/r32/eax
38043     {
38044       # if (i <= 0) break
38045       3d/compare-eax-with 0/imm32
38046       7e/jump-if-<= break/disp8
38047       (write-buffered *(ebp+8) "  ")
38048       48/decrement-eax
38049       eb/jump loop/disp8
38050     }
38051 $emit-indent:end:
38052     # . restore registers
38053     58/pop-to-eax
38054     # . epilogue
38055     89/<- %esp 5/r32/ebp
38056     5d/pop-to-ebp
38057     c3/return
38058 
38059 emit-subx-prologue:  # out: (addr buffered-file)
38060     # . prologue
38061     55/push-ebp
38062     89/<- %ebp 4/r32/esp
38063     #
38064     (write-buffered *(ebp+8) "  # . prologue\n")
38065     (write-buffered *(ebp+8) "  55/push-ebp\n")
38066     (write-buffered *(ebp+8) "  89/<- %ebp 4/r32/esp\n")
38067 $emit-subx-prologue:end:
38068     # . epilogue
38069     89/<- %esp 5/r32/ebp
38070     5d/pop-to-ebp
38071     c3/return
38072 
38073 emit-subx-epilogue:  # out: (addr buffered-file)
38074     # . prologue
38075     55/push-ebp
38076     89/<- %ebp 4/r32/esp
38077     #
38078     (write-buffered *(ebp+8) "  # . epilogue\n")
38079     (write-buffered *(ebp+8) "  89/<- %esp 5/r32/ebp\n")
38080     (write-buffered *(ebp+8) "  5d/pop-to-ebp\n")
38081     (write-buffered *(ebp+8) "  c3/return\n")
38082 $emit-subx-epilogue:end:
38083     # . epilogue
38084     89/<- %esp 5/r32/ebp
38085     5d/pop-to-ebp
38086     c3/return