https://github.com/akkartik/mu/blob/master/apps/mu.subx
    1 # The Mu computer's level-2 language, also called Mu.
    2 # http://akkartik.name/post/mu-2019-2
    3 #
    4 # To run:
    5 #   $ ./translate_subx init.linux [0-9]*.subx apps/mu.subx
    6 #   $ ./a.elf < prog.mu > prog.elf
    7 
    8 # == Goals
    9 # 1. Be memory safe. It should be impossible to corrupt the heap, or to create
   10 # a bad pointer. (Requires strong type safety.)
   11 # 2. Do as little as possible to achieve goal 1. The translator should be
   12 # implementable in machine code.
   13 #   - minimize impedance mismatch between source language and SubX target
   14 #     (e.g. programmer manages registers manually)
   15 #   - checks over syntax
   16 #     (e.g. programmer's register allocation is checked)
   17 #   - runtime checks to avoid complex static analysis
   18 #     (e.g. array indexing always checks bounds)
   19 
   20 # == Language description
   21 # A program is a sequence of function and type definitions.
   22 #
   23 # Function example:
   24 #   fn foo n: int -> result/eax: int {
   25 #     ...
   26 #   }
   27 #
   28 # Functions consist of a name, optional inputs, optional outputs and a block.
   29 #
   30 # Function inputs and outputs are variables. All variables have a type and
   31 # storage specifier. They can be placed either in memory (on the stack) or in
   32 # one of 6 named registers.
   33 #   eax ecx edx ebx esi edi
   34 # Variables in registers must be primitive 32-bit types.
   35 # Variables not explicitly placed in a register are on the stack.
   36 #
   37 # Function inputs are always passed in memory (on the stack), while outputs
   38 # are always returned in registers.
   39 #
   40 # Blocks mostly consist of statements.
   41 #
   42 # Statements mostly consist of a name, optional inputs and optional outputs.
   43 #
   44 # Statement inputs are variables or literals. Variables need to specify type
   45 # (and storage) the first time they're mentioned but not later.
   46 #
   47 # Statement outputs, like function outputs, must be variables in registers.
   48 #
   49 # Statement names must be either primitives or user-defined functions.
   50 #
   51 # Primitives can write to any register.
   52 # User-defined functions only write to hard-coded registers. Outputs of each
   53 # call must have the same registers as in the function definition.
   54 #
   55 # There are some other statement types:
   56 #   - blocks. Multiple statements surrounded by '{...}' and optionally
   57 #     prefixed with a label name and ':'
   58 #       - {
   59 #           ...
   60 #         }
   61 #       - foo: {
   62 #           ...
   63 #         }
   64 #
   65 #   - variable definitions on the stack. E.g.:
   66 #       - var foo: int
   67 #       - var bar: (array int 3)
   68 #     There's no initializer; variables are automatically initialized.
   69 #     The type of a local variable is either word-length (4 bytes) or starts with 'ref'.
   70 #
   71 #   - variables definitions in a register. E.g.:
   72 #       - var foo/eax: int <- add bar 1
   73 #     The initializer is mandatory and must be a valid instruction that writes
   74 #     a single output to the right register. In practice registers will
   75 #     usually be either initialized by primitives or copied from eax.
   76 #       - var eax: int <- foo bar quux
   77 #         var floo/ecx: int <- copy eax
   78 #
   79 # Still todo:
   80 #   global variables
   81 #   union types
   82 #
   83 # Formal types:
   84 #   A program is a linked list of functions
   85 #   A function contains:
   86 #     name: (handle array byte)
   87 #     inouts: linked list of vars  <-- 'inouts' is more precise than 'inputs'
   88 #       data: (handle var)
   89 #       next: (handle list)
   90 #     outputs: linked list of vars
   91 #       data: (handle var)
   92 #       next: (handle list)
   93 #     body: (handle block)
   94 #   A var-type contains:
   95 #     name: (handle array byte)
   96 #     type: (handle type-tree)
   97 #
   98 #   A statement can be:
   99 #     tag 0: a block
  100 #     tag 1: a simple statement (stmt1)
  101 #     tag 2: a variable defined on the stack
  102 #     tag 3: a variable defined in a register
  103 #
  104 #   A block contains:
  105 #     tag: 0
  106 #     statements: (handle list stmt)
  107 #     name: (handle array byte) -- starting with '$'
  108 #
  109 #   A regular statement contains:
  110 #     tag: 1
  111 #     operation: (handle array byte)
  112 #     inouts: (handle list operand)
  113 #     outputs: (handle list var)
  114 #
  115 #   A variable defined on the stack contains:
  116 #     tag: 2
  117 #     name: (handle array byte)
  118 #     type: (handle type-tree)
  119 #
  120 #   A variable defined in a register contains:
  121 #     tag: 3
  122 #     name: (handle array byte)
  123 #     type: (handle type-tree)
  124 #     reg: (handle array byte)
  125 
  126 # == Translation: managing the stack
  127 # Now that we know what the language looks like in the large, let's think
  128 # about how translation happens from the bottom up. One crucial piece of the
  129 # puzzle is how Mu will clean up variables defined on the stack for you.
  130 #
  131 # Assume that we maintain a 'functions' list while parsing source code. And a
  132 # 'primitives' list is a global constant. Both these contain enough information
  133 # to perform type-checking on function calls or primitive statements, respectively.
  134 #
  135 # Defining variables pushes them on a stack with the current block depth and
  136 # enough information about their location (stack offset or register).
  137 # Starting a block increments the current block id.
  138 # Each statement now has enough information to emit code for it.
  139 # Ending a block is where the magic happens:
  140 #   pop all variables at the current block depth
  141 #   emit code to restore all register variables introduced at the current depth
  142 #   emit code to clean up all stack variables at the current depth (just increment esp)
  143 #   decrement the current block depth
  144 #
  145 # Formal types:
  146 #   live-vars: stack of vars
  147 #   var:
  148 #     name: (handle array byte)
  149 #     type: (handle type-tree)
  150 #     block: int
  151 #     stack-offset: int  (added to ebp)
  152 #     register: (handle array byte)
  153 #       either usual register names
  154 #       or '*' to indicate any register
  155 #   At most one of stack-offset or register-index must be non-zero.
  156 #   A register of '*' designates a variable _template_. Only legal in formal
  157 #   parameters for primitives.
  158 
  159 # == Translating a single function call
  160 # This one's easy. Assuming we've already checked things, we just drop the
  161 # outputs (which use hard-coded registers) and emit inputs in a standard format.
  162 #
  163 # out1, out2, out3, ... <- name inout1, inout2, inout3, ...
  164 # =>
  165 # (name inout1 inout2 inout3)
  166 #
  167 # Formal types:
  168 #   functions: linked list of info
  169 #     name: (handle array byte)
  170 #     inouts: linked list of vars
  171 #     outputs: linked list of vars
  172 #     body: block (linked list of statements)
  173 
  174 # == Translating a single primitive instruction
  175 # A second crucial piece of the puzzle is how Mu converts fairly regular
  176 # primitives with their uniform syntax to SubX instructions with their gnarly
  177 # x86 details.
  178 #
  179 # Mu instructions have inputs and outputs. Primitives can have up to 2 of
  180 # them.
  181 # SubX instructions have rm32 and r32 operands.
  182 # The translation between them covers almost all the possibilities.
  183 #   Instructions with 1 inout may turn into ones with 1 rm32
  184 #     (e.g. incrementing a var on the stack)
  185 #   Instructions with 1 output may turn into ones with 1 rm32
  186 #     (e.g. incrementing a var in a register)
  187 #   1 inout and 1 output may turn into 1 rm32 and 1 r32
  188 #     (e.g. adding a var to a reg)
  189 #   2 inouts may turn into 1 rm32 and 1 r32
  190 #     (e.g. adding a reg to a var)
  191 #   1 inout and 1 literal may turn into 1 rm32 and 1 imm32
  192 #     (e.g. adding a constant to a var)
  193 #   1 output and 1 literal may turn into 1 rm32 and 1 imm32
  194 #     (e.g. adding a constant to a reg)
  195 #   2 outputs to hardcoded registers and 1 inout may turn into 1 rm32
  196 #     (special-case: divide edx:eax by a var or reg)
  197 # Observations:
  198 #   We always emit rm32. It may be the first inout or the first output.
  199 #   We may emit r32 or imm32 or neither.
  200 #   When we emit r32 it may come from first inout or second inout or first output.
  201 #
  202 # Accordingly, the formal data structure for a primitive looks like this:
  203 #   primitives: linked list of info
  204 #     name: (handle array byte)
  205 #     mu-inouts: linked list of vars to check
  206 #     mu-outputs: linked list of vars to check; at most a singleton
  207 #     subx-name: (handle array byte)
  208 #     subx-rm32: enum arg-location
  209 #     subx-r32: enum arg-location
  210 #     subx-imm32: enum arg-location
  211 #     subx-imm8: enum arg-location
  212 #     subx-disp32: enum arg-location
  213 #     subx-xm32: enum arg-location
  214 #     subx-x32: enum arg-location
  215 #   arg-location: enum
  216 #     0 means none
  217 #     1 means first inout
  218 #     2 means second inout
  219 #     3 means first output
  220 
  221 # == Translating a block
  222 # Emit block name if necessary
  223 # Emit '{'
  224 # When you encounter a statement, emit it as above
  225 # When you encounter a variable declaration
  226 #   emit any code needed for it (bzeros)
  227 #   push it on the var stack
  228 #   update register dict if necessary
  229 # When you encounter '}'
  230 #   While popping variables off the var stack until block id changes
  231 #     Emit code needed to clean up the stack
  232 #       either increment esp
  233 #       or pop into appropriate register
  234 
  235 # The rest is straightforward.
  236 
  237 == data
  238 
  239 Program:
  240 _Program-functions:  # (handle function)
  241   0/imm32
  242 _Program-functions->payload:
  243   0/imm32
  244 _Program-types:  # (handle typeinfo)
  245   0/imm32
  246 _Program-types->payload:
  247   0/imm32
  248 _Program-signatures:  # (handle function)
  249   0/imm32
  250 _Program-signatures->payload:
  251   0/imm32
  252 
  253 # Some constants for simulating the data structures described above.
  254 # Many constants here come with a type in a comment.
  255 #
  256 # Sometimes the type is of the value at that offset for the given type. For
  257 # example, if you start at a function record and move forward Function-inouts
  258 # bytes, you'll find a (handle list var).
  259 #
  260 # At other times, the type is of the constant itself. For example, the type of
  261 # the constant Function-size is (addr int). To get the size of a function,
  262 # look in *Function-size.
  263 
  264 Function-name:  # (handle array byte)
  265   0/imm32
  266 Function-inouts:  # (handle list var)
  267   8/imm32
  268 Function-outputs:  # (handle list var)
  269   0x10/imm32
  270 Function-body:  # (handle block)
  271   0x18/imm32
  272 Function-next:  # (handle function)
  273   0x20/imm32
  274 Function-size:  # (addr int)
  275   0x28/imm32/40
  276 
  277 Primitive-name:  # (handle array byte)
  278   0/imm32
  279 Primitive-inouts:  # (handle list var)
  280   8/imm32
  281 Primitive-outputs:  # (handle list var)
  282   0x10/imm32
  283 Primitive-subx-name:  # (handle array byte)
  284   0x18/imm32
  285 Primitive-subx-rm32:  # enum arg-location
  286   0x20/imm32
  287 Primitive-subx-r32:  # enum arg-location
  288   0x24/imm32
  289 Primitive-subx-imm32:  # enum arg-location
  290   0x28/imm32
  291 Primitive-subx-imm8:  # enum arg-location  -- only for bit shifts
  292   0x2c/imm32
  293 Primitive-subx-disp32:  # enum arg-location  -- only for branches
  294   0x30/imm32
  295 Primitive-subx-xm32:  # enum arg-location
  296   0x34/imm32
  297 Primitive-subx-x32:  # enum arg-location
  298   0x38/imm32
  299 Primitive-next:  # (handle function)
  300   0x3c/imm32
  301 Primitive-size:  # (addr int)
  302   0x44/imm32/68
  303 
  304 Stmt-tag:  # int
  305   0/imm32
  306 
  307 Block-stmts:  # (handle list stmt)
  308   4/imm32
  309 Block-var:  # (handle var)
  310   0xc/imm32
  311 
  312 Stmt1-operation:  # (handle array byte)
  313   4/imm32
  314 Stmt1-inouts:  # (handle stmt-var)
  315   0xc/imm32
  316 Stmt1-outputs:  # (handle stmt-var)
  317   0x14/imm32
  318 
  319 Vardef-var:  # (handle var)
  320   4/imm32
  321 
  322 Regvardef-operation:  # (handle array byte)
  323   4/imm32
  324 Regvardef-inouts:  # (handle stmt-var)
  325   0xc/imm32
  326 Regvardef-outputs:  # (handle stmt-var)  # will have exactly one element
  327   0x14/imm32
  328 
  329 Stmt-size:  # (addr int)
  330   0x1c/imm32
  331 
  332 Var-name:  # (handle array byte)
  333   0/imm32
  334 Var-type:  # (handle type-tree)
  335   8/imm32
  336 Var-block-depth:  # int -- not available until code-generation time
  337   0x10/imm32
  338 Var-offset:  # int -- not available until code-generation time
  339   0x14/imm32
  340 Var-register:  # (handle array byte) -- name of a register
  341   0x18/imm32
  342 Var-size:  # (addr int)
  343   0x20/imm32
  344 
  345 List-value:  # (handle _)
  346   0/imm32
  347 List-next:  # (handle list _)
  348   8/imm32
  349 List-size:  # (addr int)
  350   0x10/imm32
  351 
  352 # A stmt-var is like a list of vars with call-site specific metadata
  353 Stmt-var-value:  # (handle var)
  354   0/imm32
  355 Stmt-var-next:  # (handle stmt-var)
  356   8/imm32
  357 Stmt-var-is-deref:  # boolean
  358   0x10/imm32
  359 Stmt-var-size:  # (addr int)
  360   0x14/imm32
  361 
  362 # A live-var is a var augmented with information needed for tracking live
  363 # variables.
  364 Live-var-value:  # (handle var)
  365   0/imm32
  366 Live-var-register-spilled:  # boolean; only used if value is in a register, and only during code-gen
  367   8/imm32
  368 Live-var-size:  # (addr int)
  369   0xc/imm32
  370 
  371 # Types are expressed as trees (s-expressions) of type-ids (ints).
  372 
  373 Type-tree-is-atom:  # boolean
  374   0/imm32
  375 # if is-atom?
  376 Type-tree-value:  # type-id
  377   4/imm32
  378 Type-tree-value-size:  # int (for static data structure sizes)
  379   8/imm32
  380 Type-tree-parameter-name:  # (handle array byte) for type parameters
  381   8/imm32
  382 # unless is-atom?
  383 Type-tree-left:  # (addr type-tree)
  384   4/imm32
  385 Type-tree-right:  # (addr type-tree)
  386   0xc/imm32
  387 #
  388 Type-tree-size:  # (addr int)
  389   0x14/imm32
  390 
  391 # Types
  392 
  393 # TODO: Turn this data structure into valid Mu, with (fake) handles rather than addrs.
  394 Type-id:  # (stream (addr array byte))
  395   0/imm32/write  # initialized later from Primitive-type-ids
  396   0/imm32/read
  397   0x100/imm32/size
  398   # data
  399   0/imm32  # 0 reserved for literals; value is just the name
  400            # Not to be used directly, so we don't include a name here.
  401   "int"/imm32  # 1
  402   "addr"/imm32  # 2
  403   "array"/imm32  # 3
  404   "handle"/imm32  # 4
  405   "boolean"/imm32  # 5
  406   0/imm32  # 6 reserved for constants; they're like literals, but value is an int in Var-offset
  407            # Not to be used directly, so we don't include a name here.
  408   "offset"/imm32  # 7: (offset T) is guaranteed to be a 32-bit multiple of size-of(T)
  409   # 0x20
  410   "byte"/imm32  # 8
  411   0/imm32  # 9 reserved for array-capacity; value is in Type-tree-size.
  412            # Not to be used directly, so we don't include a name here.
  413   0/imm32  # 10 reserved for type parameters; value is (address array byte) in Type-tree-value2.
  414            # Not to be used directly, so we don't include a name here.
  415   "stream"/imm32  # 11
  416   "slice"/imm32  # 12
  417   "code-point"/imm32  # 13; smallest scannable unit from a text stream
  418   "grapheme"/imm32  # 14; smallest printable unit; will eventually be composed of multiple code-points, but currently corresponds 1:1
  419                     # only 4-byte graphemes in utf-8 are currently supported;
  420                     # unclear how we should deal with larger clusters.
  421   "float"/imm32     # 15
  422   # Keep Primitive-type-ids in sync if you add types here.
  423   # 0x40
  424   0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  425   0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  426   0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  427   0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  428   0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  429   0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  430 
  431 Primitive-type-ids:  # (addr int)
  432   0x40
  433 
  434 # == Type definitions
  435 # Program->types contains some typeinfo for each type definition.
  436 # Types contain vars with types, but can't specify registers.
  437 Typeinfo-id:  # type-id
  438   0/imm32
  439 Typeinfo-fields:  # (handle table (handle array byte) (handle typeinfo-entry))
  440   4/imm32
  441 # Total size must be >= 0
  442 # During parsing it may take on two additional values:
  443 #   -2: not yet initialized
  444 #   -1: in process of being computed
  445 # See populate-mu-type-sizes for details.
  446 Typeinfo-total-size-in-bytes:  # int
  447   0xc/imm32
  448 Typeinfo-next:  # (handle typeinfo)
  449   0x10/imm32
  450 Typeinfo-size:  # (addr int)
  451   0x18/imm32
  452 
  453 # Each entry in the typeinfo->fields table has a pointer to a string and a
  454 # pointer to a typeinfo-entry.
  455 Typeinfo-fields-row-size:  # (addr int)
  456   0x10/imm32
  457 
  458 # typeinfo-entry objects have information about a field in a single record type
  459 #
  460 # each field of a type is represented using two var's:
  461 #   1. the input var: expected type of the field; convenient for creating using parse-var-with-type
  462 #   2. the output var: a constant containing the byte offset; convenient for code-generation
  463 # computing the output happens after parsing; in the meantime we preserve the
  464 # order of fields in the 'index' field.
  465 Typeinfo-entry-input-var:  # (handle var)
  466   0/imm32
  467 Typeinfo-entry-index:  # int
  468   8/imm32
  469 Typeinfo-entry-output-var:  # (handle var)
  470   0xc/imm32
  471 Typeinfo-entry-size:  # (addr int)
  472   0x14/imm32
  473 
  474 == code
  475 
  476 Entry:
  477     # . prologue
  478     89/<- %ebp 4/r32/esp
  479     (new-segment *Heap-size Heap)
  480     # if (argv[1] == "test') run-tests()
  481     {
  482       # if (argc <= 1) break
  483       81 7/subop/compare *ebp 1/imm32
  484       7e/jump-if-<= break/disp8
  485       # if (argv[1] != "test") break
  486       (kernel-string-equal? *(ebp+8) "test")  # => eax
  487       3d/compare-eax-and 0/imm32/false
  488       74/jump-if-= break/disp8
  489       #
  490       (run-tests)
  491       # syscall(exit, *Num-test-failures)
  492       8b/-> *Num-test-failures 3/r32/ebx
  493       eb/jump $mu-main:end/disp8
  494     }
  495     # otherwise convert Stdin
  496     (convert-mu Stdin Stdout Stderr 0)
  497     (flush Stdout)
  498     # syscall(exit, 0)
  499     bb/copy-to-ebx 0/imm32
  500 $mu-main:end:
  501     e8/call syscall_exit/disp32
  502 
  503 convert-mu:  # in: (addr buffered-file), out: (addr buffered-file), err: (addr buffered-file), ed: (addr exit-descriptor)
  504     # . prologue
  505     55/push-ebp
  506     89/<- %ebp 4/r32/esp
  507     # . save registers
  508     50/push-eax
  509     # initialize global data structures
  510     c7 0/subop/copy *Next-block-index 1/imm32
  511     8b/-> *Primitive-type-ids 0/r32/eax
  512     89/<- *Type-id 0/r32/eax  # stream-write
  513     c7 0/subop/copy *_Program-functions 0/imm32
  514     c7 0/subop/copy *_Program-functions->payload 0/imm32
  515     c7 0/subop/copy *_Program-types 0/imm32
  516     c7 0/subop/copy *_Program-types->payload 0/imm32
  517     c7 0/subop/copy *_Program-signatures 0/imm32
  518     c7 0/subop/copy *_Program-signatures->payload 0/imm32
  519     #
  520     (parse-mu *(ebp+8) *(ebp+0x10) *(ebp+0x14))
  521     (populate-mu-type-sizes *(ebp+0x10) *(ebp+0x14))
  522 #?     (dump-typeinfos "=== typeinfos\n")
  523     (check-mu-types *(ebp+0x10) *(ebp+0x14))
  524     (emit-subx *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
  525 $convert-mu:end:
  526     # . restore registers
  527     58/pop-to-eax
  528     # . epilogue
  529     89/<- %esp 5/r32/ebp
  530     5d/pop-to-ebp
  531     c3/return
  532 
  533 test-convert-empty-input:
  534     # empty input => empty output
  535     # . prologue
  536     55/push-ebp
  537     89/<- %ebp 4/r32/esp
  538     # setup
  539     (clear-stream _test-input-stream)
  540     (clear-stream $_test-input-buffered-file->buffer)
  541     (clear-stream _test-output-stream)
  542     (clear-stream $_test-output-buffered-file->buffer)
  543     #
  544     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  545     (flush _test-output-buffered-file)
  546     (check-stream-equal _test-output-stream "" "F - test-convert-empty-input")
  547     # . epilogue
  548     89/<- %esp 5/r32/ebp
  549     5d/pop-to-ebp
  550     c3/return
  551 
  552 test-convert-function-skeleton:
  553     # . prologue
  554     55/push-ebp
  555     89/<- %ebp 4/r32/esp
  556     # setup
  557     (clear-stream _test-input-stream)
  558     (clear-stream $_test-input-buffered-file->buffer)
  559     (clear-stream _test-output-stream)
  560     (clear-stream $_test-output-buffered-file->buffer)
  561     #
  562     (write _test-input-stream "fn foo {\n")
  563     (write _test-input-stream "}\n")
  564     # convert
  565     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  566     (flush _test-output-buffered-file)
  567 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
  573     # check output
  574     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-skeleton/0")
  575     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-skeleton/1")
  576     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-skeleton/2")
  577     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-skeleton/3")
  578     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-skeleton/4")
  579     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-skeleton/5")
  580     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-skeleton/6")
  581     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-skeleton/7")
  582     # . epilogue
  583     89/<- %esp 5/r32/ebp
  584     5d/pop-to-ebp
  585     c3/return
  586 
  587 test-convert-multiple-function-skeletons:
  588     # . prologue
  589     55/push-ebp
  590     89/<- %ebp 4/r32/esp
  591     # setup
  592     (clear-stream _test-input-stream)
  593     (clear-stream $_test-input-buffered-file->buffer)
  594     (clear-stream _test-output-stream)
  595     (clear-stream $_test-output-buffered-file->buffer)
  596     #
  597     (write _test-input-stream "fn foo {\n")
  598     (write _test-input-stream "}\n")
  599     (write _test-input-stream "fn bar {\n")
  600     (write _test-input-stream "}\n")
  601     # convert
  602     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  603     (flush _test-output-buffered-file)
  604 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
  610     # check first function
  611     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-multiple-function-skeletons/0")
  612     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-multiple-function-skeletons/1")
  613     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-multiple-function-skeletons/2")
  614     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-multiple-function-skeletons/3")
  615     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-multiple-function-skeletons/4")
  616     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-multiple-function-skeletons/5")
  617     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-multiple-function-skeletons/6")
  618     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-multiple-function-skeletons/7")
  619     # check second function
  620     (check-next-stream-line-equal _test-output-stream "bar:"                    "F - test-convert-multiple-function-skeletons/10")
  621     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-multiple-function-skeletons/11")
  622     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-multiple-function-skeletons/12")
  623     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-multiple-function-skeletons/13")
  624     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-multiple-function-skeletons/14")
  625     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-multiple-function-skeletons/15")
  626     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-multiple-function-skeletons/16")
  627     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-multiple-function-skeletons/17")
  628     # . epilogue
  629     89/<- %esp 5/r32/ebp
  630     5d/pop-to-ebp
  631     c3/return
  632 
  633 test-convert-function-with-arg:
  634     # . prologue
  635     55/push-ebp
  636     89/<- %ebp 4/r32/esp
  637     # setup
  638     (clear-stream _test-input-stream)
  639     (clear-stream $_test-input-buffered-file->buffer)
  640     (clear-stream _test-output-stream)
  641     (clear-stream $_test-output-buffered-file->buffer)
  642     #
  643     (write _test-input-stream "fn foo n: int {\n")
  644     (write _test-input-stream "}\n")
  645     # convert
  646     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  647     (flush _test-output-buffered-file)
  648 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
  654     # check output
  655     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-arg/0")
  656     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-arg/1")
  657     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-arg/2")
  658     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-arg/3")
  659     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-arg/4")
  660     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-arg/5")
  661     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-arg/6")
  662     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-arg/7")
  663     # . epilogue
  664     89/<- %esp 5/r32/ebp
  665     5d/pop-to-ebp
  666     c3/return
  667 
  668 test-convert-function-with-arg-and-body:
  669     # . prologue
  670     55/push-ebp
  671     89/<- %ebp 4/r32/esp
  672     # setup
  673     (clear-stream _test-input-stream)
  674     (clear-stream $_test-input-buffered-file->buffer)
  675     (clear-stream _test-output-stream)
  676     (clear-stream $_test-output-buffered-file->buffer)
  677     #
  678     (write _test-input-stream "fn foo n: int {\n")
  679     (write _test-input-stream "  increment n\n")
  680     (write _test-input-stream "}\n")
  681     # convert
  682     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  683     (flush _test-output-buffered-file)
  684 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
  690     # check output
  691     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-arg-and-body/0")
  692     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-arg-and-body/1")
  693     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-arg-and-body/2")
  694     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-arg-and-body/3")
  695     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-arg-and-body/4")
  696     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-arg-and-body/5")
  697     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *(ebp+0x00000008)"  "F - test-convert-function-with-arg-and-body/6")
  698     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-arg-and-body/7")
  699     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-arg-and-body/8")
  700     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-arg-and-body/9")
  701     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-arg-and-body/10")
  702     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-arg-and-body/11")
  703     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-arg-and-body/12")
  704     # . epilogue
  705     89/<- %esp 5/r32/ebp
  706     5d/pop-to-ebp
  707     c3/return
  708 
  709 test-convert-function-distinguishes-args:
  710     # . prologue
  711     55/push-ebp
  712     89/<- %ebp 4/r32/esp
  713     # setup
  714     (clear-stream _test-input-stream)
  715     (clear-stream $_test-input-buffered-file->buffer)
  716     (clear-stream _test-output-stream)
  717     (clear-stream $_test-output-buffered-file->buffer)
  718     #
  719     (write _test-input-stream "fn foo a: int, b: int {\n")
  720     (write _test-input-stream "  increment b\n")
  721     (write _test-input-stream "}\n")
  722     # convert
  723     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  724     (flush _test-output-buffered-file)
  725 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
  731     # check output
  732     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-distinguishes-args/0")
  733     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-distinguishes-args/1")
  734     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-distinguishes-args/2")
  735     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-distinguishes-args/3")
  736     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-distinguishes-args/4")
  737     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-distinguishes-args/5")
  738     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *(ebp+0x0000000c)"  "F - test-convert-function-distinguishes-args/6")
  739     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-distinguishes-args/7")
  740     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-distinguishes-args/8")
  741     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-distinguishes-args/9")
  742     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-distinguishes-args/10")
  743     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-distinguishes-args/11")
  744     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-distinguishes-args/12")
  745     # . epilogue
  746     89/<- %esp 5/r32/ebp
  747     5d/pop-to-ebp
  748     c3/return
  749 
  750 test-convert-function-with-return-literal:
  751     # . prologue
  752     55/push-ebp
  753     89/<- %ebp 4/r32/esp
  754     # setup
  755     (clear-stream _test-input-stream)
  756     (clear-stream $_test-input-buffered-file->buffer)
  757     (clear-stream _test-output-stream)
  758     (clear-stream $_test-output-buffered-file->buffer)
  759     #
  760     (write _test-input-stream "fn foo -> x/eax: int {\n")
  761     (write _test-input-stream "  return 0\n")
  762     (write _test-input-stream "}\n")
  763     # convert
  764     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  765     (flush _test-output-buffered-file)
  766 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
  772     # check output
  773     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-literal/0")
  774     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-literal/1")
  775     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-literal/2")
  776     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-literal/3")
  777     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-literal/4")
  778     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-literal/5")
  779     (check-next-stream-line-equal _test-output-stream "    c7 0/subop/copy %eax 0/imm32"  "F - test-convert-function-with-return-literal/6")
  780     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-literal/7")
  781     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-literal/8")
  782     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-literal/9")
  783     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-literal/10")
  784     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-literal/11")
  785     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-literal/12")
  786     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-literal/13")
  787     # . epilogue
  788     89/<- %esp 5/r32/ebp
  789     5d/pop-to-ebp
  790     c3/return
  791 
  792 test-convert-function-with-return:
  793     # . prologue
  794     55/push-ebp
  795     89/<- %ebp 4/r32/esp
  796     # setup
  797     (clear-stream _test-input-stream)
  798     (clear-stream $_test-input-buffered-file->buffer)
  799     (clear-stream _test-output-stream)
  800     (clear-stream $_test-output-buffered-file->buffer)
  801     #
  802     (write _test-input-stream "fn foo -> x/eax: int {\n")
  803     (write _test-input-stream "  var y: int\n")
  804     (write _test-input-stream "  return y\n")
  805     (write _test-input-stream "}\n")
  806     # convert
  807     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  808     (flush _test-output-buffered-file)
  809 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
  815     # check output
  816     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return/0")
  817     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return/1")
  818     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return/2")
  819     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return/3")
  820     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return/4")
  821     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return/5")
  822     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-return/6")  # y
  823     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0xfffffffc) 0x00000000/r32" "F - test-convert-function-with-return/7")
  824     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-return/8")
  825     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return/9")
  826     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return/10")
  827     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return/11")
  828     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return/12")
  829     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return/13")
  830     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return/14")
  831     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return/15")
  832     # . epilogue
  833     89/<- %esp 5/r32/ebp
  834     5d/pop-to-ebp
  835     c3/return
  836 
  837 test-convert-function-with-return-register:
  838     # . prologue
  839     55/push-ebp
  840     89/<- %ebp 4/r32/esp
  841     # setup
  842     (clear-stream _test-input-stream)
  843     (clear-stream $_test-input-buffered-file->buffer)
  844     (clear-stream _test-output-stream)
  845     (clear-stream $_test-output-buffered-file->buffer)
  846     #
  847     (write _test-input-stream "fn foo -> x/eax: int {\n")
  848     (write _test-input-stream "  var y/eax: int <- copy 3\n")
  849     (write _test-input-stream "  return y\n")
  850     (write _test-input-stream "}\n")
  851     # convert
  852     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  853     (flush _test-output-buffered-file)
  854 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
  860     # check output
  861     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-register/0")
  862     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-register/1")
  863     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-register/2")
  864     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-register/3")
  865     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-register/4")
  866     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-register/5")
  867     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-with-return-register/6")
  868     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 3/imm32"  "F - test-convert-function-with-return-register/7")
  869     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32" "F - test-convert-function-with-return-register/8")
  870     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-with-return-register/9")
  871     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-register/10")
  872     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-register/11")
  873     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-register/12")
  874     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-register/13")
  875     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-register/14")
  876     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-register/15")
  877     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-register/16")
  878     # . epilogue
  879     89/<- %esp 5/r32/ebp
  880     5d/pop-to-ebp
  881     c3/return
  882 
  883 test-convert-function-with-literal-arg:
  884     # . prologue
  885     55/push-ebp
  886     89/<- %ebp 4/r32/esp
  887     # setup
  888     (clear-stream _test-input-stream)
  889     (clear-stream $_test-input-buffered-file->buffer)
  890     (clear-stream _test-output-stream)
  891     (clear-stream $_test-output-buffered-file->buffer)
  892     #
  893     (write _test-input-stream "fn foo a: int, b: int -> _/eax: int {\n")
  894     (write _test-input-stream "  var result/eax: int <- copy a\n")
  895     (write _test-input-stream "  result <- add 1\n")
  896     (write _test-input-stream "  return result\n")
  897     (write _test-input-stream "}\n")
  898     # convert
  899     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  900     (flush _test-output-buffered-file)
  901 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
  907     # check output
  908     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-literal-arg/0")
  909     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-literal-arg/1")
  910     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-literal-arg/2")
  911     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-literal-arg/3")
  912     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-literal-arg/4")
  913     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-literal-arg/5")
  914     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-with-literal-arg/6")
  915     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-function-with-literal-arg/7")
  916     (check-next-stream-line-equal _test-output-stream "    05/add-to-eax 1/imm32"  "F - test-convert-function-with-literal-arg/8")
  917     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32" "F - test-convert-function-with-literal-arg/9")
  918     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-with-literal-arg/10")
  919     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-literal-arg/11")
  920     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-literal-arg/12")
  921     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-literal-arg/13")
  922     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-literal-arg/14")
  923     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-literal-arg/15")
  924     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-literal-arg/16")
  925     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-literal-arg/17")
  926     # . epilogue
  927     89/<- %esp 5/r32/ebp
  928     5d/pop-to-ebp
  929     c3/return
  930 
  931 test-convert-function-with-literal-arg-2:
  932     # . prologue
  933     55/push-ebp
  934     89/<- %ebp 4/r32/esp
  935     # setup
  936     (clear-stream _test-input-stream)
  937     (clear-stream $_test-input-buffered-file->buffer)
  938     (clear-stream _test-output-stream)
  939     (clear-stream $_test-output-buffered-file->buffer)
  940     #
  941     (write _test-input-stream "fn foo a: int, b: int -> _/ebx: int {\n")
  942     (write _test-input-stream "  var result/ebx: int <- copy a\n")
  943     (write _test-input-stream "  result <- add 1\n")
  944     (write _test-input-stream "  return result\n")
  945     (write _test-input-stream "}\n")
  946     # convert
  947     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  948     (flush _test-output-buffered-file)
  949 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
  955     # check output
  956     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-literal-arg-2/0")
  957     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-literal-arg-2/1")
  958     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-literal-arg-2/2")
  959     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-literal-arg-2/3")
  960     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-literal-arg-2/4")
  961     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-literal-arg-2/5")
  962     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ebx"  "F - test-convert-function-with-literal-arg-2/6")
  963     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000003/r32"  "F - test-convert-function-with-literal-arg-2/7")
  964     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %ebx 1/imm32"  "F - test-convert-function-with-literal-arg-2/8")
  965     (check-next-stream-line-equal _test-output-stream "    8b/-> %ebx 0x00000003/r32" "F - test-convert-function-with-literal-arg-2/9")
  966     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-with-literal-arg-2/10")
  967     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-literal-arg-2/11")
  968     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-literal-arg-2/12")
  969     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-literal-arg-2/13")
  970     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-literal-arg-2/14")
  971     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-literal-arg-2/15")
  972     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-literal-arg-2/16")
  973     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-literal-arg-2/17")
  974     # . epilogue
  975     89/<- %esp 5/r32/ebp
  976     5d/pop-to-ebp
  977     c3/return
  978 
  979 test-convert-function-call-with-literal-arg:
  980     # . prologue
  981     55/push-ebp
  982     89/<- %ebp 4/r32/esp
  983     # setup
  984     (clear-stream _test-input-stream)
  985     (clear-stream $_test-input-buffered-file->buffer)
  986     (clear-stream _test-output-stream)
  987     (clear-stream $_test-output-buffered-file->buffer)
  988     #
  989     (write _test-input-stream "fn main -> _/ebx: int {\n")
  990     (write _test-input-stream "  var result/eax: int <- do-add 3 4\n")
  991     (write _test-input-stream "  return result\n")
  992     (write _test-input-stream "}\n")
  993     (write _test-input-stream "fn do-add a: int, b: int -> _/eax: int {\n")
  994     (write _test-input-stream "  var result/eax: int <- copy a\n")
  995     (write _test-input-stream "  result <- add b\n")
  996     (write _test-input-stream "  return result\n")
  997     (write _test-input-stream "}\n")
  998     # convert
  999     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1000     (flush _test-output-buffered-file)
 1001 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1007     # check output
 1008     (check-next-stream-line-equal _test-output-stream "main:"                   "F - test-convert-function-call-with-literal-arg/0")
 1009     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-literal-arg/1")
 1010     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-literal-arg/2")
 1011     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-literal-arg/3")
 1012     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-literal-arg/4")
 1013     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:loop:"  "F - test-convert-function-call-with-literal-arg/5")
 1014     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-call-with-literal-arg/6")
 1015     (check-next-stream-line-equal _test-output-stream "    (do-add 3 4)"        "F - test-convert-function-call-with-literal-arg/7")
 1016     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/8")
 1017     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-function-with-local-var-in-reg/9")
 1018     (check-next-stream-line-equal _test-output-stream "    e9/jump $main:0x00000001:break/disp32"  "F - test-convert-function-call-with-literal-arg/10")
 1019     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-literal-arg/11")
 1020     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:break:" "F - test-convert-function-call-with-literal-arg/12")
 1021     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-literal-arg/13")
 1022     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-literal-arg/14")
 1023     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-literal-arg/15")
 1024     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-literal-arg/16")
 1025     (check-next-stream-line-equal _test-output-stream "do-add:"                 "F - test-convert-function-call-with-literal-arg/17")
 1026     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-literal-arg/18")
 1027     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-literal-arg/19")
 1028     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-literal-arg/20")
 1029     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-literal-arg/21")
 1030     (check-next-stream-line-equal _test-output-stream "$do-add:0x00000002:loop:"  "F - test-convert-function-call-with-literal-arg/22")
 1031     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-call-with-literal-arg/23")
 1032     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-function-call-with-literal-arg/24")
 1033     (check-next-stream-line-equal _test-output-stream "    03/add *(ebp+0x0000000c) 0x00000000/r32"  "F - test-convert-function-call-with-literal-arg/25")
 1034     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32" "F - test-convert-function-call-with-literal-arg/26")
 1035     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-call-with-literal-arg/27")
 1036     (check-next-stream-line-equal _test-output-stream "    e9/jump $do-add:0x00000002:break/disp32"  "F - test-convert-function-call-with-literal-arg/28")
 1037     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-literal-arg/29")
 1038     (check-next-stream-line-equal _test-output-stream "$do-add:0x00000002:break:"  "F - test-convert-function-call-with-literal-arg/30")
 1039     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-literal-arg/31")
 1040     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-literal-arg/32")
 1041     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-literal-arg/33")
 1042     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-literal-arg/34")
 1043     # . epilogue
 1044     89/<- %esp 5/r32/ebp
 1045     5d/pop-to-ebp
 1046     c3/return
 1047 
 1048 test-convert-function-call-with-signature:
 1049     # . prologue
 1050     55/push-ebp
 1051     89/<- %ebp 4/r32/esp
 1052     # setup
 1053     (clear-stream _test-input-stream)
 1054     (clear-stream $_test-input-buffered-file->buffer)
 1055     (clear-stream _test-output-stream)
 1056     (clear-stream $_test-output-buffered-file->buffer)
 1057     #
 1058     (write _test-input-stream "fn main -> _/ebx: int {\n")
 1059     (write _test-input-stream "  var result/eax: int <- do-add 3 4\n")
 1060     (write _test-input-stream "  return result\n")
 1061     (write _test-input-stream "}\n")
 1062     (write _test-input-stream "sig do-add a: int, b: int -> _/eax: int\n")
 1063     # convert
 1064     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1065     (flush _test-output-buffered-file)
 1066 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1072     # check output
 1073     (check-next-stream-line-equal _test-output-stream "main:"                   "F - test-convert-function-call-with-signature/0")
 1074     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-signature/1")
 1075     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-signature/2")
 1076     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-signature/3")
 1077     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-signature/4")
 1078     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:loop:"  "F - test-convert-function-call-with-signature/5")
 1079     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-call-with-literal-arg/6")
 1080     (check-next-stream-line-equal _test-output-stream "    (do-add 3 4)"        "F - test-convert-function-call-with-signature/6")
 1081     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/8")
 1082     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-function-with-local-var-in-reg/9")
 1083     (check-next-stream-line-equal _test-output-stream "    e9/jump $main:0x00000001:break/disp32"  "F - test-convert-function-call-with-literal-arg/10")
 1084     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-signature/7")
 1085     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:break:" "F - test-convert-function-call-with-signature/8")
 1086     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-signature/9")
 1087     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-signature/10")
 1088     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-signature/11")
 1089     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-signature/12")
 1090     # . epilogue
 1091     89/<- %esp 5/r32/ebp
 1092     5d/pop-to-ebp
 1093     c3/return
 1094 
 1095 test-convert-function-with-local-var-in-mem:
 1096     # . prologue
 1097     55/push-ebp
 1098     89/<- %ebp 4/r32/esp
 1099     # setup
 1100     (clear-stream _test-input-stream)
 1101     (clear-stream $_test-input-buffered-file->buffer)
 1102     (clear-stream _test-output-stream)
 1103     (clear-stream $_test-output-buffered-file->buffer)
 1104     #
 1105     (write _test-input-stream "fn foo {\n")
 1106     (write _test-input-stream "  var x: int\n")
 1107     (write _test-input-stream "  increment x\n")
 1108     (write _test-input-stream "}\n")
 1109     # convert
 1110     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1111     (flush _test-output-buffered-file)
 1112 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1118     # check output
 1119     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-mem/0")
 1120     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-mem/1")
 1121     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-mem/2")
 1122     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-mem/3")
 1123     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-mem/4")
 1124     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-mem/5")
 1125     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-in-mem/6")
 1126     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-local-var-in-mem/7")
 1127     (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")
 1128     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-mem/9")
 1129     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-mem/10")
 1130     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-mem/11")
 1131     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-mem/12")
 1132     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-mem/13")
 1133     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-mem/14")
 1134     # . epilogue
 1135     89/<- %esp 5/r32/ebp
 1136     5d/pop-to-ebp
 1137     c3/return
 1138 
 1139 test-convert-invalid-literal:
 1140     # . prologue
 1141     55/push-ebp
 1142     89/<- %ebp 4/r32/esp
 1143     # setup
 1144     (clear-stream _test-input-stream)
 1145     (clear-stream $_test-input-buffered-file->buffer)
 1146     (clear-stream _test-output-stream)
 1147     (clear-stream $_test-output-buffered-file->buffer)
 1148     (clear-stream _test-error-stream)
 1149     (clear-stream $_test-error-buffered-file->buffer)
 1150     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1151     68/push 0/imm32
 1152     68/push 0/imm32
 1153     89/<- %edx 4/r32/esp
 1154     (tailor-exit-descriptor %edx 0x10)
 1155     #
 1156     (write _test-input-stream "fn foo {\n")
 1157     (write _test-input-stream "  increment 1n\n")
 1158     (write _test-input-stream "}\n")
 1159     # convert
 1160     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1161     # registers except esp clobbered at this point
 1162     # restore ed
 1163     89/<- %edx 4/r32/esp
 1164     (flush _test-output-buffered-file)
 1165     (flush _test-error-buffered-file)
 1166 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1172     # check output
 1173     (check-stream-equal _test-output-stream  ""  "F - test-convert-invalid-literal: output should be empty")
 1174     (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")
 1175     # check that stop(1) was called
 1176     (check-ints-equal *(edx+4) 2 "F - test-convert-invalid-literal: exit status")
 1177     # don't restore from ebp
 1178     81 0/subop/add %esp 8/imm32
 1179     # . epilogue
 1180     5d/pop-to-ebp
 1181     c3/return
 1182 
 1183 test-local-var-in-mem-has-no-initializer:
 1184     # . prologue
 1185     55/push-ebp
 1186     89/<- %ebp 4/r32/esp
 1187     # setup
 1188     (clear-stream _test-input-stream)
 1189     (clear-stream $_test-input-buffered-file->buffer)
 1190     (clear-stream _test-output-stream)
 1191     (clear-stream $_test-output-buffered-file->buffer)
 1192     (clear-stream _test-error-stream)
 1193     (clear-stream $_test-error-buffered-file->buffer)
 1194     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1195     68/push 0/imm32
 1196     68/push 0/imm32
 1197     89/<- %edx 4/r32/esp
 1198     (tailor-exit-descriptor %edx 0x10)
 1199     #
 1200     (write _test-input-stream "fn foo {\n")
 1201     (write _test-input-stream "  var x: int <- copy 0\n")
 1202     (write _test-input-stream "  increment x\n")
 1203     (write _test-input-stream "}\n")
 1204     # convert
 1205     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1206     # registers except esp clobbered at this point
 1207     # restore ed
 1208     89/<- %edx 4/r32/esp
 1209     (flush _test-output-buffered-file)
 1210     (flush _test-error-buffered-file)
 1211 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1217     # check output
 1218     (check-stream-equal _test-output-stream  ""  "F - test-var-in-mem-has-no-initializer: output should be empty")
 1219     (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")
 1220     # check that stop(1) was called
 1221     (check-ints-equal *(edx+4) 2 "F - test-var-in-mem-has-no-initializer: exit status")
 1222     # don't restore from ebp
 1223     81 0/subop/add %esp 8/imm32
 1224     # . epilogue
 1225     5d/pop-to-ebp
 1226     c3/return
 1227 
 1228 test-convert-function-with-local-var-with-compound-type-in-mem:
 1229     # . prologue
 1230     55/push-ebp
 1231     89/<- %ebp 4/r32/esp
 1232     # setup
 1233     (clear-stream _test-input-stream)
 1234     (clear-stream $_test-input-buffered-file->buffer)
 1235     (clear-stream _test-output-stream)
 1236     (clear-stream $_test-output-buffered-file->buffer)
 1237     #
 1238     (write _test-input-stream "fn foo {\n")
 1239     (write _test-input-stream "  var x: (addr int)\n")
 1240     (write _test-input-stream "  copy-to x, 0\n")
 1241     (write _test-input-stream "}\n")
 1242     # convert
 1243     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1244     (flush _test-output-buffered-file)
 1245 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1251     # check output
 1252     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-with-compound-type-in-mem/0")
 1253     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-with-compound-type-in-mem/1")
 1254     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-with-compound-type-in-mem/2")
 1255     (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")
 1256     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-with-compound-type-in-mem/4")
 1257     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-with-compound-type-in-mem/5")
 1258     (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")
 1259     (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")
 1260     (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")
 1261     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-with-compound-type-in-mem/9")
 1262     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-with-compound-type-in-mem/10")
 1263     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-with-compound-type-in-mem/11")
 1264     (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")
 1265     (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")
 1266     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-with-compound-type-in-mem/14")
 1267     # . epilogue
 1268     89/<- %esp 5/r32/ebp
 1269     5d/pop-to-ebp
 1270     c3/return
 1271 
 1272 test-convert-function-with-local-var-in-reg:
 1273     # . prologue
 1274     55/push-ebp
 1275     89/<- %ebp 4/r32/esp
 1276     # setup
 1277     (clear-stream _test-input-stream)
 1278     (clear-stream $_test-input-buffered-file->buffer)
 1279     (clear-stream _test-output-stream)
 1280     (clear-stream $_test-output-buffered-file->buffer)
 1281     #
 1282     (write _test-input-stream "fn foo {\n")
 1283     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 1284     (write _test-input-stream "  x <- increment\n")
 1285     (write _test-input-stream "}\n")
 1286     # convert
 1287     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1288     (flush _test-output-buffered-file)
 1289 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1295     # check output
 1296     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-reg/0")
 1297     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-reg/1")
 1298     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-reg/2")
 1299     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-reg/3")
 1300     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-reg/4")
 1301     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-reg/5")
 1302     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-local-var-in-reg/6")
 1303     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-convert-function-with-local-var-in-reg/7")
 1304     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-convert-function-with-local-var-in-reg/8")
 1305     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-local-var-in-reg/9")
 1306     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-reg/10")
 1307     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-reg/11")
 1308     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-reg/12")
 1309     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-reg/13")
 1310     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-reg/14")
 1311     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-reg/15")
 1312     # . epilogue
 1313     89/<- %esp 5/r32/ebp
 1314     5d/pop-to-ebp
 1315     c3/return
 1316 
 1317 test-convert-function-with-allocate:
 1318     # . prologue
 1319     55/push-ebp
 1320     89/<- %ebp 4/r32/esp
 1321     # setup
 1322     (clear-stream _test-input-stream)
 1323     (clear-stream $_test-input-buffered-file->buffer)
 1324     (clear-stream _test-output-stream)
 1325     (clear-stream $_test-output-buffered-file->buffer)
 1326     #
 1327     (write _test-input-stream "fn foo {\n")
 1328     (write _test-input-stream "  var x/ecx: (addr handle int) <- copy 0\n")
 1329     (write _test-input-stream "  allocate x\n")
 1330     (write _test-input-stream "}\n")
 1331     # convert
 1332     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1333     (flush _test-output-buffered-file)
 1334 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1340     # check output
 1341     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-allocate/0")
 1342     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-allocate/1")
 1343     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-allocate/2")
 1344     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-allocate/3")
 1345     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-allocate/4")
 1346     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-allocate/5")
 1347     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-allocate/6")
 1348     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-function-with-allocate/7")
 1349     (check-next-stream-line-equal _test-output-stream "    (allocate Heap 0x00000004 %ecx)"  "F - test-convert-function-with-allocate/8")  # 4 = size-of(int)
 1350     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-allocate/9")
 1351     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-allocate/10")
 1352     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-allocate/11")
 1353     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-allocate/12")
 1354     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-allocate/13")
 1355     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-allocate/14")
 1356     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-allocate/15")
 1357     # . epilogue
 1358     89/<- %esp 5/r32/ebp
 1359     5d/pop-to-ebp
 1360     c3/return
 1361 
 1362 test-initializer-in-hex:
 1363     # . prologue
 1364     55/push-ebp
 1365     89/<- %ebp 4/r32/esp
 1366     # setup
 1367     (clear-stream _test-input-stream)
 1368     (clear-stream $_test-input-buffered-file->buffer)
 1369     (clear-stream _test-output-stream)
 1370     (clear-stream $_test-output-buffered-file->buffer)
 1371     (clear-stream _test-error-stream)
 1372     (clear-stream $_test-error-buffered-file->buffer)
 1373     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1374     68/push 0/imm32
 1375     68/push 0/imm32
 1376     89/<- %edx 4/r32/esp
 1377     (tailor-exit-descriptor %edx 0x10)
 1378     #
 1379     (write _test-input-stream "fn foo {\n")
 1380     (write _test-input-stream "  var x/ecx: int <- copy 10\n")
 1381     (write _test-input-stream "}\n")
 1382     # convert
 1383     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1384     # registers except esp clobbered at this point
 1385     # restore ed
 1386     89/<- %edx 4/r32/esp
 1387     (flush _test-output-buffered-file)
 1388     (flush _test-error-buffered-file)
 1389 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1395     # check output
 1396     (check-stream-equal _test-output-stream  ""  "F - test-initializer-in-hex: output should be empty")
 1397     (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")
 1398     # check that stop(1) was called
 1399     (check-ints-equal *(edx+4) 2 "F - test-initializer-in-hex: exit status")
 1400     # don't restore from ebp
 1401     81 0/subop/add %esp 8/imm32
 1402     # . epilogue
 1403     5d/pop-to-ebp
 1404     c3/return
 1405 
 1406 test-convert-function-with-second-local-var-in-same-reg:
 1407     # . prologue
 1408     55/push-ebp
 1409     89/<- %ebp 4/r32/esp
 1410     # setup
 1411     (clear-stream _test-input-stream)
 1412     (clear-stream $_test-input-buffered-file->buffer)
 1413     (clear-stream _test-output-stream)
 1414     (clear-stream $_test-output-buffered-file->buffer)
 1415     #
 1416     (write _test-input-stream "fn foo {\n")
 1417     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 1418     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
 1419     (write _test-input-stream "  y <- increment\n")
 1420     (write _test-input-stream "}\n")
 1421     # convert
 1422     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1423     (flush _test-output-buffered-file)
 1424 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1430     # check output
 1431     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-second-local-var-in-same-reg/0")
 1432     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-second-local-var-in-same-reg/1")
 1433     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-second-local-var-in-same-reg/2")
 1434     (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")
 1435     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-second-local-var-in-same-reg/4")
 1436     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-second-local-var-in-same-reg/5")
 1437     (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")
 1438     (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")
 1439     (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")
 1440     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-convert-function-with-second-local-var-in-same-reg/9")
 1441     (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")
 1442     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-second-local-var-in-same-reg/11")
 1443     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-second-local-var-in-same-reg/12")
 1444     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-second-local-var-in-same-reg/13")
 1445     (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")
 1446     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-second-local-var-in-same-reg/15")
 1447     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-second-local-var-in-same-reg/16")
 1448     # . epilogue
 1449     89/<- %esp 5/r32/ebp
 1450     5d/pop-to-ebp
 1451     c3/return
 1452 
 1453 test-read-clobbered-reg-var:
 1454     # . prologue
 1455     55/push-ebp
 1456     89/<- %ebp 4/r32/esp
 1457     # setup
 1458     (clear-stream _test-input-stream)
 1459     (clear-stream $_test-input-buffered-file->buffer)
 1460     (clear-stream _test-output-stream)
 1461     (clear-stream $_test-output-buffered-file->buffer)
 1462     (clear-stream _test-error-stream)
 1463     (clear-stream $_test-error-buffered-file->buffer)
 1464     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)  # bytes of args in call to convert-mu
 1465     68/push 0/imm32
 1466     68/push 0/imm32
 1467     89/<- %edx 4/r32/esp
 1468     (tailor-exit-descriptor %edx 0x10)
 1469     #
 1470     (write _test-input-stream "fn foo {\n")
 1471     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 1472     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
 1473     (write _test-input-stream "  x <- increment\n")
 1474     (write _test-input-stream "}\n")
 1475     # convert
 1476     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1477     # registers except esp clobbered at this point
 1478     # restore ed
 1479     89/<- %edx 4/r32/esp
 1480     (flush _test-output-buffered-file)
 1481     (flush _test-error-buffered-file)
 1482 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1488     # check output
 1489     (check-stream-equal _test-output-stream  ""  "F - test-read-clobbered-reg-var: output should be empty")
 1490     (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")
 1491     # check that stop(1) was called
 1492     (check-ints-equal *(edx+4) 2 "F - test-read-clobbered-reg-var: exit status")
 1493     # don't restore from ebp
 1494     81 0/subop/add %esp 8/imm32
 1495     # . epilogue
 1496     5d/pop-to-ebp
 1497     c3/return
 1498 
 1499 test-overlapping-int-fp-registers:
 1500     # . prologue
 1501     55/push-ebp
 1502     89/<- %ebp 4/r32/esp
 1503     # setup
 1504     (clear-stream _test-input-stream)
 1505     (clear-stream $_test-input-buffered-file->buffer)
 1506     (clear-stream _test-output-stream)
 1507     (clear-stream $_test-output-buffered-file->buffer)
 1508     (clear-stream _test-error-stream)
 1509     (clear-stream $_test-error-buffered-file->buffer)
 1510     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)  # bytes of args in call to convert-mu
 1511     68/push 0/imm32
 1512     68/push 0/imm32
 1513     89/<- %edx 4/r32/esp
 1514     (tailor-exit-descriptor %edx 0x10)
 1515     #
 1516     (write _test-input-stream "fn foo {\n")
 1517     (write _test-input-stream "  var x/eax: int <- copy 3\n")
 1518     (write _test-input-stream "  var y/xmm0: float <- convert x\n")
 1519     (write _test-input-stream "  x <- increment\n")
 1520     (write _test-input-stream "}\n")
 1521     # convert
 1522     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1523     # registers except esp clobbered at this point
 1524     # restore ed
 1525     89/<- %edx 4/r32/esp
 1526     (flush _test-output-buffered-file)
 1527     (flush _test-error-buffered-file)
 1528 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1534     # no errors
 1535     (check-next-stream-line-equal _test-error-stream  ""  "F - test-overlapping-int-fp-registers: error message")
 1536     # don't bother checking the generated code
 1537     # don't restore from ebp
 1538     81 0/subop/add %esp 8/imm32
 1539     # . epilogue
 1540     5d/pop-to-ebp
 1541     c3/return
 1542 
 1543 test-convert-function-call:
 1544     # . prologue
 1545     55/push-ebp
 1546     89/<- %ebp 4/r32/esp
 1547     # setup
 1548     (clear-stream _test-input-stream)
 1549     (clear-stream $_test-input-buffered-file->buffer)
 1550     (clear-stream _test-output-stream)
 1551     (clear-stream $_test-output-buffered-file->buffer)
 1552     #
 1553     (write _test-input-stream "fn main -> _/ebx: int {\n")
 1554     (write _test-input-stream "  var result/ebx: int <- foo\n")
 1555     (write _test-input-stream "  return result\n")
 1556     (write _test-input-stream "}\n")
 1557     (write _test-input-stream "fn foo -> result/ebx: int {\n")
 1558     (write _test-input-stream "  var result/ebx: int <- copy 3\n")
 1559     (write _test-input-stream "  return result\n")
 1560     (write _test-input-stream "}\n")
 1561     # convert
 1562     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1563     (flush _test-output-buffered-file)
 1564 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1570     # check output
 1571     (check-next-stream-line-equal _test-output-stream "main:"                   "F - test-convert-function-call/0")
 1572     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call/1")
 1573     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call/2")
 1574     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call/3")
 1575     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call/4")
 1576     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:loop:"  "F - test-convert-function-call/5")
 1577     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ebx"  "F - test-convert-function-call-with-literal-arg/6")
 1578     (check-next-stream-line-equal _test-output-stream "    (foo)"               "F - test-convert-function-call/6")
 1579     (check-next-stream-line-equal _test-output-stream "    8b/-> %ebx 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/8")
 1580     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-call-with-literal-arg/27")
 1581     (check-next-stream-line-equal _test-output-stream "    e9/jump $main:0x00000001:break/disp32"  "F - test-convert-function-call-with-literal-arg/10")
 1582     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call/7")
 1583     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:break:" "F - test-convert-function-call/8")
 1584     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call/9")
 1585     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call/10")
 1586     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call/11")
 1587     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call/12")
 1588     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call/13")
 1589     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call/14")
 1590     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call/15")
 1591     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call/16")
 1592     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call/17")
 1593     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"  "F - test-convert-function-call/18")
 1594     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ebx"  "F - test-convert-function-call-with-literal-arg/6")
 1595     (check-next-stream-line-equal _test-output-stream "    bb/copy-to-ebx 3/imm32"  "F - test-convert-function-call/19")
 1596     (check-next-stream-line-equal _test-output-stream "    8b/-> %ebx 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/8")
 1597     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-call-with-literal-arg/27")
 1598     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-call-with-literal-arg/10")
 1599     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call/20")
 1600     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-call/21")
 1601     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call/22")
 1602     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call/23")
 1603     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call/24")
 1604     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call/25")
 1605     # . epilogue
 1606     89/<- %esp 5/r32/ebp
 1607     5d/pop-to-ebp
 1608     c3/return
 1609 
 1610 test-convert-function-call-with-inout-with-compound-type:
 1611     # . prologue
 1612     55/push-ebp
 1613     89/<- %ebp 4/r32/esp
 1614     # setup
 1615     (clear-stream _test-input-stream)
 1616     (clear-stream $_test-input-buffered-file->buffer)
 1617     (clear-stream _test-output-stream)
 1618     (clear-stream $_test-output-buffered-file->buffer)
 1619     #
 1620     (write _test-input-stream "fn f {\n")
 1621     (write _test-input-stream "  var x: (addr int)\n")
 1622     (write _test-input-stream "  g x\n")
 1623     (write _test-input-stream "}\n")
 1624     (write _test-input-stream "fn g a: (addr int) {\n")
 1625     (write _test-input-stream "}\n")
 1626     # convert
 1627     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1628     (flush _test-output-buffered-file)
 1629 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1635     # check output
 1636     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-inout-with-compound-type/0")
 1637     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-inout-with-compound-type/1")
 1638     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-inout-with-compound-type/2")
 1639     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-inout-with-compound-type/3")
 1640     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-inout-with-compound-type/4")
 1641     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"     "F - test-convert-function-call-with-inout-with-compound-type/5")
 1642     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-call-with-inout-with-compound-type/6")
 1643     (check-next-stream-line-equal _test-output-stream "    (g *(ebp+0xfffffffc))"  "F - test-convert-function-call-with-inout-with-compound-type/7")
 1644     (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")
 1645     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-inout-with-compound-type/9")
 1646     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"    "F - test-convert-function-call-with-inout-with-compound-type/10")
 1647     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-inout-with-compound-type/11")
 1648     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-inout-with-compound-type/12")
 1649     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-inout-with-compound-type/13")
 1650     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-inout-with-compound-type/14")
 1651     (check-next-stream-line-equal _test-output-stream "g:"                      "F - test-convert-function-call-with-inout-with-compound-type/15")
 1652     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-inout-with-compound-type/16")
 1653     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-inout-with-compound-type/17")
 1654     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-inout-with-compound-type/18")
 1655     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-inout-with-compound-type/19")
 1656     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-inout-with-compound-type/20")
 1657     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-inout-with-compound-type/21")
 1658     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-inout-with-compound-type/22")
 1659     # . epilogue
 1660     89/<- %esp 5/r32/ebp
 1661     5d/pop-to-ebp
 1662     c3/return
 1663 
 1664 test-convert-function-call-with-inout-with-type-parameter:
 1665     # . prologue
 1666     55/push-ebp
 1667     89/<- %ebp 4/r32/esp
 1668     # setup
 1669     (clear-stream _test-input-stream)
 1670     (clear-stream $_test-input-buffered-file->buffer)
 1671     (clear-stream _test-output-stream)
 1672     (clear-stream $_test-output-buffered-file->buffer)
 1673     (clear-stream _test-error-stream)
 1674     (clear-stream $_test-error-buffered-file->buffer)
 1675     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1676     68/push 0/imm32
 1677     68/push 0/imm32
 1678     89/<- %edx 4/r32/esp
 1679     (tailor-exit-descriptor %edx 0x10)
 1680     #
 1681     (write _test-input-stream "fn f {\n")
 1682     (write _test-input-stream "  var x: (addr int)\n")
 1683     (write _test-input-stream "  g x\n")
 1684     (write _test-input-stream "}\n")
 1685     (write _test-input-stream "fn g a: (addr _) {\n")
 1686     (write _test-input-stream "}\n")
 1687     # convert
 1688     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1689     # registers except esp clobbered at this point
 1690     # restore ed
 1691     89/<- %edx 4/r32/esp
 1692     (flush _test-output-buffered-file)
 1693     (flush _test-error-buffered-file)
 1694 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1700     # no error; types matched
 1701     (check-stream-equal _test-error-stream  ""  "F - test-convert-function-call-with-inout-with-type-parameter: error stream should be empty")
 1702     # don't bother checking the generated code; that's in the test 'test-local-clobbered-by-fn-output' below
 1703     # don't restore from ebp
 1704     81 0/subop/add %esp 8/imm32
 1705     # . epilogue
 1706     5d/pop-to-ebp
 1707     c3/return
 1708 
 1709 test-convert-function-call-with-incorrect-inout-type:
 1710     # . prologue
 1711     55/push-ebp
 1712     89/<- %ebp 4/r32/esp
 1713     # setup
 1714     (clear-stream _test-input-stream)
 1715     (clear-stream $_test-input-buffered-file->buffer)
 1716     (clear-stream _test-output-stream)
 1717     (clear-stream $_test-output-buffered-file->buffer)
 1718     (clear-stream _test-error-stream)
 1719     (clear-stream $_test-error-buffered-file->buffer)
 1720     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1721     68/push 0/imm32
 1722     68/push 0/imm32
 1723     89/<- %edx 4/r32/esp
 1724     (tailor-exit-descriptor %edx 0x10)
 1725     #
 1726     (write _test-input-stream "fn f {\n")
 1727     (write _test-input-stream "  var x: int\n")
 1728     (write _test-input-stream "  g x\n")
 1729     (write _test-input-stream "}\n")
 1730     (write _test-input-stream "fn g a: foo {\n")
 1731     (write _test-input-stream "}\n")
 1732     # convert
 1733     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1734     # registers except esp clobbered at this point
 1735     # restore ed
 1736     89/<- %edx 4/r32/esp
 1737     (flush _test-output-buffered-file)
 1738     (flush _test-error-buffered-file)
 1739 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1745     # check output
 1746     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-incorrect-inout-type: output should be empty")
 1747     (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")
 1748     # check that stop(1) was called
 1749     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-incorrect-inout-type: exit status")
 1750     # don't restore from ebp
 1751     81 0/subop/add %esp 8/imm32
 1752     5d/pop-to-ebp
 1753     c3/return
 1754 
 1755 test-convert-function-call-with-inout-with-incorrect-compound-type:
 1756     # . prologue
 1757     55/push-ebp
 1758     89/<- %ebp 4/r32/esp
 1759     # setup
 1760     (clear-stream _test-input-stream)
 1761     (clear-stream $_test-input-buffered-file->buffer)
 1762     (clear-stream _test-output-stream)
 1763     (clear-stream $_test-output-buffered-file->buffer)
 1764     (clear-stream _test-error-stream)
 1765     (clear-stream $_test-error-buffered-file->buffer)
 1766     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1767     68/push 0/imm32
 1768     68/push 0/imm32
 1769     89/<- %edx 4/r32/esp
 1770     (tailor-exit-descriptor %edx 0x10)
 1771     #
 1772     (write _test-input-stream "fn f {\n")
 1773     (write _test-input-stream "  var x: (addr int)\n")
 1774     (write _test-input-stream "  g x\n")
 1775     (write _test-input-stream "}\n")
 1776     (write _test-input-stream "fn g a: (addr bool) {\n")
 1777     (write _test-input-stream "}\n")
 1778     # convert
 1779     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1780     # registers except esp clobbered at this point
 1781     # restore ed
 1782     89/<- %edx 4/r32/esp
 1783     (flush _test-output-buffered-file)
 1784     (flush _test-error-buffered-file)
 1785 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1791     # check output
 1792     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-inout-with-incorrect-compound-type: output should be empty")
 1793     (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")
 1794     # don't restore from ebp
 1795     81 0/subop/add %esp 8/imm32
 1796     # . epilogue
 1797     5d/pop-to-ebp
 1798     c3/return
 1799 
 1800 test-convert-function-call-with-inout-with-multiple-type-parameters:
 1801     # . prologue
 1802     55/push-ebp
 1803     89/<- %ebp 4/r32/esp
 1804     # setup
 1805     (clear-stream _test-input-stream)
 1806     (clear-stream $_test-input-buffered-file->buffer)
 1807     (clear-stream _test-output-stream)
 1808     (clear-stream $_test-output-buffered-file->buffer)
 1809     (clear-stream _test-error-stream)
 1810     (clear-stream $_test-error-buffered-file->buffer)
 1811     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1812     68/push 0/imm32
 1813     68/push 0/imm32
 1814     89/<- %edx 4/r32/esp
 1815     (tailor-exit-descriptor %edx 0x10)
 1816     #
 1817     (write _test-input-stream "fn f {\n")
 1818     (write _test-input-stream "  var x: (addr int)\n")
 1819     (write _test-input-stream "  var y: (addr int)\n")
 1820     (write _test-input-stream "  g x, y\n")
 1821     (write _test-input-stream "}\n")
 1822     (write _test-input-stream "fn g a: (addr _), b: (addr _) {\n")
 1823     (write _test-input-stream "}\n")
 1824     # convert
 1825     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1826     # registers except esp clobbered at this point
 1827     # restore ed
 1828     89/<- %edx 4/r32/esp
 1829     (flush _test-output-buffered-file)
 1830     (flush _test-error-buffered-file)
 1831 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1837     # no errors
 1838     (check-stream-equal _test-error-stream  ""  "F - test-convert-function-call-with-inout-with-multiple-type-parameters: error stream should be empty")
 1839     # don't bother checking the generated code
 1840     # don't restore from ebp
 1841     81 0/subop/add %esp 8/imm32
 1842     # . epilogue
 1843     5d/pop-to-ebp
 1844     c3/return
 1845 
 1846 test-type-parameter-matches-rest-of-type:
 1847     # . prologue
 1848     55/push-ebp
 1849     89/<- %ebp 4/r32/esp
 1850     # setup
 1851     (clear-stream _test-input-stream)
 1852     (clear-stream $_test-input-buffered-file->buffer)
 1853     (clear-stream _test-output-stream)
 1854     (clear-stream $_test-output-buffered-file->buffer)
 1855     (clear-stream _test-error-stream)
 1856     (clear-stream $_test-error-buffered-file->buffer)
 1857     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1858     68/push 0/imm32
 1859     68/push 0/imm32
 1860     89/<- %edx 4/r32/esp
 1861     (tailor-exit-descriptor %edx 0x10)
 1862     #
 1863     (write _test-input-stream "fn f {\n")
 1864     (write _test-input-stream "  var x: (addr array int)\n")
 1865     (write _test-input-stream "  g x\n")
 1866     (write _test-input-stream "}\n")
 1867     (write _test-input-stream "fn g a: (addr _) {\n")
 1868     (write _test-input-stream "}\n")
 1869     # convert
 1870     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1871     # registers except esp clobbered at this point
 1872     # restore ed
 1873     89/<- %edx 4/r32/esp
 1874     (flush _test-output-buffered-file)
 1875     (flush _test-error-buffered-file)
 1876 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1882     # no errors
 1883     (check-stream-equal _test-error-stream  ""  "F - test-type-parameter-matches-rest-of-type: error stream should be empty")
 1884     # don't bother checking the generated code
 1885     # don't restore from ebp
 1886     81 0/subop/add %esp 8/imm32
 1887     # . epilogue
 1888     5d/pop-to-ebp
 1889     c3/return
 1890 
 1891 test-convert-function-call-with-inout-with-incompatible-type-parameters:
 1892     # . prologue
 1893     55/push-ebp
 1894     89/<- %ebp 4/r32/esp
 1895     # setup
 1896     (clear-stream _test-input-stream)
 1897     (clear-stream $_test-input-buffered-file->buffer)
 1898     (clear-stream _test-output-stream)
 1899     (clear-stream $_test-output-buffered-file->buffer)
 1900     (clear-stream _test-error-stream)
 1901     (clear-stream $_test-error-buffered-file->buffer)
 1902     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1903     68/push 0/imm32
 1904     68/push 0/imm32
 1905     89/<- %edx 4/r32/esp
 1906     (tailor-exit-descriptor %edx 0x10)
 1907     #
 1908     (write _test-input-stream "fn f {\n")
 1909     (write _test-input-stream "  var x: (addr int)\n")
 1910     (write _test-input-stream "  var y: (addr boolean)\n")
 1911     (write _test-input-stream "  g x, y\n")
 1912     (write _test-input-stream "}\n")
 1913     (write _test-input-stream "fn g a: (addr _T), b: (addr _T) {\n")
 1914     (write _test-input-stream "}\n")
 1915     # convert
 1916     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1917     # registers except esp clobbered at this point
 1918     # restore ed
 1919     89/<- %edx 4/r32/esp
 1920     (flush _test-output-buffered-file)
 1921     (flush _test-error-buffered-file)
 1922 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1928     # check output
 1929     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-inout-with-incompatible-type-parameters: output should be empty")
 1930     (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")
 1931     # don't restore from ebp
 1932     81 0/subop/add %esp 8/imm32
 1933     # . epilogue
 1934     5d/pop-to-ebp
 1935     c3/return
 1936 
 1937 test-convert-function-call-with-too-few-inouts:
 1938     # . prologue
 1939     55/push-ebp
 1940     89/<- %ebp 4/r32/esp
 1941     # setup
 1942     (clear-stream _test-input-stream)
 1943     (clear-stream $_test-input-buffered-file->buffer)
 1944     (clear-stream _test-output-stream)
 1945     (clear-stream $_test-output-buffered-file->buffer)
 1946     (clear-stream _test-error-stream)
 1947     (clear-stream $_test-error-buffered-file->buffer)
 1948     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1949     68/push 0/imm32
 1950     68/push 0/imm32
 1951     89/<- %edx 4/r32/esp
 1952     (tailor-exit-descriptor %edx 0x10)
 1953     #
 1954     (write _test-input-stream "fn f {\n")
 1955     (write _test-input-stream "  g\n")
 1956     (write _test-input-stream "}\n")
 1957     (write _test-input-stream "fn g a: int {\n")
 1958     (write _test-input-stream "}\n")
 1959     # convert
 1960     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1961     # registers except esp clobbered at this point
 1962     # restore ed
 1963     89/<- %edx 4/r32/esp
 1964     (flush _test-output-buffered-file)
 1965     (flush _test-error-buffered-file)
 1966 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1972     # check output
 1973     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-few-inouts: output should be empty")
 1974     (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")
 1975     # check that stop(1) was called
 1976     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-few-inouts: exit status")
 1977     # don't restore from ebp
 1978     81 0/subop/add %esp 8/imm32
 1979     5d/pop-to-ebp
 1980     c3/return
 1981 
 1982 test-convert-function-call-with-too-many-inouts:
 1983     # . prologue
 1984     55/push-ebp
 1985     89/<- %ebp 4/r32/esp
 1986     # setup
 1987     (clear-stream _test-input-stream)
 1988     (clear-stream $_test-input-buffered-file->buffer)
 1989     (clear-stream _test-output-stream)
 1990     (clear-stream $_test-output-buffered-file->buffer)
 1991     (clear-stream _test-error-stream)
 1992     (clear-stream $_test-error-buffered-file->buffer)
 1993     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1994     68/push 0/imm32
 1995     68/push 0/imm32
 1996     89/<- %edx 4/r32/esp
 1997     (tailor-exit-descriptor %edx 0x10)
 1998     #
 1999     (write _test-input-stream "fn f {\n")
 2000     (write _test-input-stream "  var x: int\n")
 2001     (write _test-input-stream "  g x\n")
 2002     (write _test-input-stream "}\n")
 2003     (write _test-input-stream "fn g {\n")
 2004     (write _test-input-stream "}\n")
 2005     # convert
 2006     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2007     # registers except esp clobbered at this point
 2008     # restore ed
 2009     89/<- %edx 4/r32/esp
 2010     (flush _test-output-buffered-file)
 2011     (flush _test-error-buffered-file)
 2012 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2018     # check output
 2019     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-many-inouts: output should be empty")
 2020     (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")
 2021     # check that stop(1) was called
 2022     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-many-inouts: exit status")
 2023     # don't restore from ebp
 2024     81 0/subop/add %esp 8/imm32
 2025     5d/pop-to-ebp
 2026     c3/return
 2027 
 2028 test-convert-function-call-with-incorrect-output-type:
 2029     # . prologue
 2030     55/push-ebp
 2031     89/<- %ebp 4/r32/esp
 2032     # setup
 2033     (clear-stream _test-input-stream)
 2034     (clear-stream $_test-input-buffered-file->buffer)
 2035     (clear-stream _test-output-stream)
 2036     (clear-stream $_test-output-buffered-file->buffer)
 2037     (clear-stream _test-error-stream)
 2038     (clear-stream $_test-error-buffered-file->buffer)
 2039     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2040     68/push 0/imm32
 2041     68/push 0/imm32
 2042     89/<- %edx 4/r32/esp
 2043     (tailor-exit-descriptor %edx 0x10)
 2044     #
 2045     (write _test-input-stream "fn f {\n")
 2046     (write _test-input-stream "  var x/eax: int <- g\n")
 2047     (write _test-input-stream "}\n")
 2048     (write _test-input-stream "fn g -> a/eax: foo {\n")
 2049     (write _test-input-stream "}\n")
 2050     # convert
 2051     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2052     # registers except esp clobbered at this point
 2053     # restore ed
 2054     89/<- %edx 4/r32/esp
 2055     (flush _test-output-buffered-file)
 2056     (flush _test-error-buffered-file)
 2057 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2063     # check output
 2064     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-incorrect-output-type: output should be empty")
 2065     (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")
 2066     # check that stop(1) was called
 2067     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-incorrect-output-type: exit status")
 2068     # don't restore from ebp
 2069     81 0/subop/add %esp 8/imm32
 2070     5d/pop-to-ebp
 2071     c3/return
 2072 
 2073 test-convert-function-call-with-too-few-outputs:
 2074     # . prologue
 2075     55/push-ebp
 2076     89/<- %ebp 4/r32/esp
 2077     # setup
 2078     (clear-stream _test-input-stream)
 2079     (clear-stream $_test-input-buffered-file->buffer)
 2080     (clear-stream _test-output-stream)
 2081     (clear-stream $_test-output-buffered-file->buffer)
 2082     (clear-stream _test-error-stream)
 2083     (clear-stream $_test-error-buffered-file->buffer)
 2084     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2085     68/push 0/imm32
 2086     68/push 0/imm32
 2087     89/<- %edx 4/r32/esp
 2088     (tailor-exit-descriptor %edx 0x10)
 2089     #
 2090     (write _test-input-stream "fn f {\n")
 2091     (write _test-input-stream "  g\n")
 2092     (write _test-input-stream "}\n")
 2093     (write _test-input-stream "fn g -> a/eax: int {\n")
 2094     (write _test-input-stream "}\n")
 2095     # convert
 2096     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2097     # registers except esp clobbered at this point
 2098     # restore ed
 2099     89/<- %edx 4/r32/esp
 2100     (flush _test-output-buffered-file)
 2101     (flush _test-error-buffered-file)
 2102 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2108     # check output
 2109     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-few-outputs: output should be empty")
 2110     (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")
 2111     # check that stop(1) was called
 2112     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-few-outputs: exit status")
 2113     # don't restore from ebp
 2114     81 0/subop/add %esp 8/imm32
 2115     5d/pop-to-ebp
 2116     c3/return
 2117 
 2118 test-convert-function-call-with-too-many-outputs:
 2119     # . prologue
 2120     55/push-ebp
 2121     89/<- %ebp 4/r32/esp
 2122     # setup
 2123     (clear-stream _test-input-stream)
 2124     (clear-stream $_test-input-buffered-file->buffer)
 2125     (clear-stream _test-output-stream)
 2126     (clear-stream $_test-output-buffered-file->buffer)
 2127     (clear-stream _test-error-stream)
 2128     (clear-stream $_test-error-buffered-file->buffer)
 2129     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2130     68/push 0/imm32
 2131     68/push 0/imm32
 2132     89/<- %edx 4/r32/esp
 2133     (tailor-exit-descriptor %edx 0x10)
 2134     #
 2135     (write _test-input-stream "fn f {\n")
 2136     (write _test-input-stream "  var x/eax: int <- g\n")
 2137     (write _test-input-stream "}\n")
 2138     (write _test-input-stream "fn g {\n")
 2139     (write _test-input-stream "}\n")
 2140     # convert
 2141     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2142     # registers except esp clobbered at this point
 2143     # restore ed
 2144     89/<- %edx 4/r32/esp
 2145     (flush _test-output-buffered-file)
 2146     (flush _test-error-buffered-file)
 2147 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2153     # check output
 2154     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-many-outputs: output should be empty")
 2155     (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")
 2156     # check that stop(1) was called
 2157     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-many-outputs: exit status")
 2158     # don't restore from ebp
 2159     81 0/subop/add %esp 8/imm32
 2160     5d/pop-to-ebp
 2161     c3/return
 2162 
 2163 test-convert-function-call-with-missing-output-register:
 2164     # . prologue
 2165     55/push-ebp
 2166     89/<- %ebp 4/r32/esp
 2167     # setup
 2168     (clear-stream _test-input-stream)
 2169     (clear-stream $_test-input-buffered-file->buffer)
 2170     (clear-stream _test-output-stream)
 2171     (clear-stream $_test-output-buffered-file->buffer)
 2172     (clear-stream _test-error-stream)
 2173     (clear-stream $_test-error-buffered-file->buffer)
 2174     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2175     68/push 0/imm32
 2176     68/push 0/imm32
 2177     89/<- %edx 4/r32/esp
 2178     (tailor-exit-descriptor %edx 0x10)
 2179     #
 2180     (write _test-input-stream "fn f {\n")
 2181     (write _test-input-stream "  var x: int\n")
 2182     (write _test-input-stream "  x <- g\n")
 2183     (write _test-input-stream "}\n")
 2184     (write _test-input-stream "fn g -> a/eax: int {\n")
 2185     (write _test-input-stream "}\n")
 2186     # convert
 2187     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2188     # registers except esp clobbered at this point
 2189     # restore ed
 2190     89/<- %edx 4/r32/esp
 2191     (flush _test-output-buffered-file)
 2192     (flush _test-error-buffered-file)
 2193 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2199     # check output
 2200     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-missing-output-register: output should be empty")
 2201     (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")
 2202     # check that stop(1) was called
 2203     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-missing-output-register: exit status")
 2204     # don't restore from ebp
 2205     81 0/subop/add %esp 8/imm32
 2206     5d/pop-to-ebp
 2207     c3/return
 2208 
 2209 test-convert-function-call-with-incorrect-output-register:
 2210     # . prologue
 2211     55/push-ebp
 2212     89/<- %ebp 4/r32/esp
 2213     # setup
 2214     (clear-stream _test-input-stream)
 2215     (clear-stream $_test-input-buffered-file->buffer)
 2216     (clear-stream _test-output-stream)
 2217     (clear-stream $_test-output-buffered-file->buffer)
 2218     (clear-stream _test-error-stream)
 2219     (clear-stream $_test-error-buffered-file->buffer)
 2220     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2221     68/push 0/imm32
 2222     68/push 0/imm32
 2223     89/<- %edx 4/r32/esp
 2224     (tailor-exit-descriptor %edx 0x10)
 2225     #
 2226     (write _test-input-stream "fn f {\n")
 2227     (write _test-input-stream "  var x/ecx: int <- g\n")
 2228     (write _test-input-stream "}\n")
 2229     (write _test-input-stream "fn g -> a/eax: int {\n")
 2230     (write _test-input-stream "}\n")
 2231     # convert
 2232     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2233     # registers except esp clobbered at this point
 2234     # restore ed
 2235     89/<- %edx 4/r32/esp
 2236     (flush _test-output-buffered-file)
 2237     (flush _test-error-buffered-file)
 2238 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2244     # check output
 2245     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-incorrect-output-register: output should be empty")
 2246     (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")
 2247     # check that stop(1) was called
 2248     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-incorrect-output-register: exit status")
 2249     # don't restore from ebp
 2250     81 0/subop/add %esp 8/imm32
 2251     5d/pop-to-ebp
 2252     c3/return
 2253 
 2254 test-convert-function-with-local-var-dereferenced:
 2255     # . prologue
 2256     55/push-ebp
 2257     89/<- %ebp 4/r32/esp
 2258     # setup
 2259     (clear-stream _test-input-stream)
 2260     (clear-stream $_test-input-buffered-file->buffer)
 2261     (clear-stream _test-output-stream)
 2262     (clear-stream $_test-output-buffered-file->buffer)
 2263     #
 2264     (write _test-input-stream "fn foo {\n")
 2265     (write _test-input-stream "  var x/ecx: (addr int) <- copy 0\n")
 2266     (write _test-input-stream "  increment *x\n")
 2267     (write _test-input-stream "}\n")
 2268     # convert
 2269     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2270     (flush _test-output-buffered-file)
 2271 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2277     # check output
 2278     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-dereferenced/0")
 2279     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-dereferenced/1")
 2280     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-dereferenced/2")
 2281     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-dereferenced/3")
 2282     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-dereferenced/4")
 2283     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-dereferenced/5")
 2284     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-local-var-dereferenced/6")
 2285     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-function-with-local-var-dereferenced/7")
 2286     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *ecx"  "F - test-convert-function-with-local-var-dereferenced/8")
 2287     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-local-var-dereferenced/9")
 2288     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-dereferenced/10")
 2289     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-dereferenced/11")
 2290     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-dereferenced/12")
 2291     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-dereferenced/13")
 2292     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-dereferenced/14")
 2293     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-dereferenced/15")
 2294     # . epilogue
 2295     89/<- %esp 5/r32/ebp
 2296     5d/pop-to-ebp
 2297     c3/return
 2298 
 2299 # variables of type 'byte' are not allowed on the stack
 2300 test-convert-function-with-byte-operations:
 2301     # . prologue
 2302     55/push-ebp
 2303     89/<- %ebp 4/r32/esp
 2304     # setup
 2305     (clear-stream _test-input-stream)
 2306     (clear-stream $_test-input-buffered-file->buffer)
 2307     (clear-stream _test-output-stream)
 2308     (clear-stream $_test-output-buffered-file->buffer)
 2309     #
 2310     (write _test-input-stream "fn foo {\n")
 2311     (write _test-input-stream "  var x/eax: byte <- copy 0\n")
 2312     (write _test-input-stream "  var y/ecx: byte <- copy 0\n")
 2313     (write _test-input-stream "  y <- copy-byte x\n")
 2314     (write _test-input-stream "  var z/edx: (addr byte) <- copy 0\n")
 2315     (write _test-input-stream "  y <- copy-byte *z\n")
 2316     (write _test-input-stream "  copy-byte-to *z, x\n")
 2317     (write _test-input-stream "}\n")
 2318     # convert
 2319     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2320     (flush _test-output-buffered-file)
 2321 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2327     # check output
 2328     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-function-with-byte-operations/0")
 2329     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-function-with-byte-operations/1")
 2330     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-function-with-byte-operations/2")
 2331     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-function-with-byte-operations/3")
 2332     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-function-with-byte-operations/4")
 2333     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-function-with-byte-operations/5")
 2334     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-function-with-byte-operations/6")
 2335     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-function-with-byte-operations/7")
 2336     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-function-with-byte-operations/8")
 2337     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"                  "F - test-convert-function-with-byte-operations/9")
 2338     (check-next-stream-line-equal _test-output-stream "    8a/byte-> %eax 0x00000001/r32"           "F - test-convert-function-with-byte-operations/10")
 2339     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %edx"                    "F - test-convert-function-with-byte-operations/11")
 2340     (check-next-stream-line-equal _test-output-stream "    ba/copy-to-edx 0/imm32"                  "F - test-convert-function-with-byte-operations/12")
 2341     (check-next-stream-line-equal _test-output-stream "    8a/byte-> *edx 0x00000001/r32"           "F - test-convert-function-with-byte-operations/13")
 2342     (check-next-stream-line-equal _test-output-stream "    88/byte<- *edx 0x00000000/r32"           "F - test-convert-function-with-byte-operations/14")
 2343     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %edx"                     "F - test-convert-function-with-byte-operations/15")
 2344     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-function-with-byte-operations/16")
 2345     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-function-with-byte-operations/17")
 2346     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-function-with-byte-operations/18")
 2347     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-function-with-byte-operations/19")
 2348     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-function-with-byte-operations/20")
 2349     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-function-with-byte-operations/21")
 2350     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-function-with-byte-operations/22")
 2351     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-function-with-byte-operations/23")
 2352     # . epilogue
 2353     89/<- %esp 5/r32/ebp
 2354     5d/pop-to-ebp
 2355     c3/return
 2356 
 2357 # variables of type 'byte' _can_ be function args. They then occupy 4 bytes.
 2358 test-copy-byte-var-from-fn-arg:
 2359     # . prologue
 2360     55/push-ebp
 2361     89/<- %ebp 4/r32/esp
 2362     # setup
 2363     (clear-stream _test-input-stream)
 2364     (clear-stream $_test-input-buffered-file->buffer)
 2365     (clear-stream _test-output-stream)
 2366     (clear-stream $_test-output-buffered-file->buffer)
 2367     #
 2368     (write _test-input-stream "fn foo x: byte, y: int {\n")
 2369     (write _test-input-stream "  var a/eax: byte <- copy x\n")
 2370     (write _test-input-stream "  var b/eax: int <- copy y\n")
 2371     (write _test-input-stream "}\n")
 2372     # convert
 2373     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2374     (flush _test-output-buffered-file)
 2375 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2381     # check output
 2382     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-copy-byte-from-fn-arg/0")
 2383     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-copy-byte-from-fn-arg/1")
 2384     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-copy-byte-from-fn-arg/2")
 2385     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-copy-byte-from-fn-arg/3")
 2386     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-copy-byte-from-fn-arg/4")
 2387     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-copy-byte-from-fn-arg/5")
 2388     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-copy-byte-from-fn-arg/6")
 2389     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-copy-byte-from-fn-arg/7")
 2390     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x0000000c) 0x00000000/r32"  "F - test-copy-byte-from-fn-arg/8")
 2391     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"   "F - test-copy-byte-from-fn-arg/9")
 2392     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-copy-byte-from-fn-arg/10")
 2393     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-copy-byte-from-fn-arg/11")
 2394     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-copy-byte-from-fn-arg/12")
 2395     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-copy-byte-from-fn-arg/13")
 2396     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-copy-byte-from-fn-arg/14")
 2397     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-copy-byte-from-fn-arg/15")
 2398     # . epilogue
 2399     89/<- %esp 5/r32/ebp
 2400     5d/pop-to-ebp
 2401     c3/return
 2402 
 2403 test-convert-compare-register-with-literal:
 2404     # . prologue
 2405     55/push-ebp
 2406     89/<- %ebp 4/r32/esp
 2407     # setup
 2408     (clear-stream _test-input-stream)
 2409     (clear-stream $_test-input-buffered-file->buffer)
 2410     (clear-stream _test-output-stream)
 2411     (clear-stream $_test-output-buffered-file->buffer)
 2412     #
 2413     (write _test-input-stream "fn foo {\n")
 2414     (write _test-input-stream "  var x/ecx: int <- copy 0\n")
 2415     (write _test-input-stream "  compare x, 0\n")
 2416     (write _test-input-stream "}\n")
 2417     # convert
 2418     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2419     (flush _test-output-buffered-file)
 2420 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2426     # check output
 2427     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-compare-register-with-literal/0")
 2428     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-compare-register-with-literal/1")
 2429     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-compare-register-with-literal/2")
 2430     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-compare-register-with-literal/3")
 2431     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-compare-register-with-literal/4")
 2432     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-compare-register-with-literal/5")
 2433     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-compare-register-with-literal/6")
 2434     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-compare-register-with-literal/7")
 2435     (check-next-stream-line-equal _test-output-stream "    81 7/subop/compare %ecx 0/imm32"  "F - test-convert-compare-register-with-literal/8")
 2436     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-compare-register-with-literal/9")
 2437     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-compare-register-with-literal/10")
 2438     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-compare-register-with-literal/11")
 2439     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-compare-register-with-literal/12")
 2440     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-compare-register-with-literal/13")
 2441     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-compare-register-with-literal/14")
 2442     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-compare-register-with-literal/15")
 2443     # . epilogue
 2444     89/<- %esp 5/r32/ebp
 2445     5d/pop-to-ebp
 2446     c3/return
 2447 
 2448 test-unknown-variable:
 2449     # . prologue
 2450     55/push-ebp
 2451     89/<- %ebp 4/r32/esp
 2452     # setup
 2453     (clear-stream _test-input-stream)
 2454     (clear-stream $_test-input-buffered-file->buffer)
 2455     (clear-stream _test-output-stream)
 2456     (clear-stream $_test-output-buffered-file->buffer)
 2457     (clear-stream _test-error-stream)
 2458     (clear-stream $_test-error-buffered-file->buffer)
 2459     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2460     68/push 0/imm32
 2461     68/push 0/imm32
 2462     89/<- %edx 4/r32/esp
 2463     (tailor-exit-descriptor %edx 0x10)
 2464     #
 2465     (write _test-input-stream "fn foo {\n")
 2466     (write _test-input-stream "  compare x, 0\n")
 2467     (write _test-input-stream "}\n")
 2468     # convert
 2469     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2470     # registers except esp clobbered at this point
 2471     # restore ed
 2472     89/<- %edx 4/r32/esp
 2473     (flush _test-output-buffered-file)
 2474     (flush _test-error-buffered-file)
 2475 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2481     # check output
 2482     (check-stream-equal _test-output-stream  ""  "F - test-unknown-variable: output should be empty")
 2483     (check-next-stream-line-equal _test-error-stream  "fn foo: unknown variable 'x'"  "F - test-unknown-variable: error message")
 2484     # check that stop(1) was called
 2485     (check-ints-equal *(edx+4) 2 "F - test-unknown-variable: exit status")
 2486     # don't restore from ebp
 2487     81 0/subop/add %esp 8/imm32
 2488     # . epilogue
 2489     5d/pop-to-ebp
 2490     c3/return
 2491 
 2492 test-convert-function-with-local-var-in-block:
 2493     # . prologue
 2494     55/push-ebp
 2495     89/<- %ebp 4/r32/esp
 2496     # setup
 2497     (clear-stream _test-input-stream)
 2498     (clear-stream $_test-input-buffered-file->buffer)
 2499     (clear-stream _test-output-stream)
 2500     (clear-stream $_test-output-buffered-file->buffer)
 2501     #
 2502     (write _test-input-stream "fn foo {\n")
 2503     (write _test-input-stream "  {\n")
 2504     (write _test-input-stream "    var x: int\n")
 2505     (write _test-input-stream "    increment x\n")
 2506     (write _test-input-stream "  }\n")
 2507     (write _test-input-stream "}\n")
 2508     # convert
 2509     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2510     (flush _test-output-buffered-file)
 2511 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2517     # check output
 2518     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-block/0")
 2519     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-block/1")
 2520     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-block/2")
 2521     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-block/3")
 2522     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-block/4")
 2523     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-block/5")
 2524     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-local-var-in-block/6")
 2525     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-local-var-in-block/7")
 2526     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-local-var-in-block/8")
 2527     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-local-var-in-block/9")
 2528     (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")
 2529     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-local-var-in-block/11")
 2530     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-local-var-in-block/12")
 2531     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-block/13")
 2532     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-block/14")
 2533     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-block/15")
 2534     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-block/16")
 2535     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-block/17")
 2536     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-block/18")
 2537     # . epilogue
 2538     89/<- %esp 5/r32/ebp
 2539     5d/pop-to-ebp
 2540     c3/return
 2541 
 2542 test-convert-function-with-local-var-in-mem-after-block:
 2543     # . prologue
 2544     55/push-ebp
 2545     89/<- %ebp 4/r32/esp
 2546     # setup
 2547     (clear-stream _test-input-stream)
 2548     (clear-stream $_test-input-buffered-file->buffer)
 2549     (clear-stream _test-output-stream)
 2550     (clear-stream $_test-output-buffered-file->buffer)
 2551     #
 2552     (write _test-input-stream "fn foo {\n")
 2553     (write _test-input-stream "  {\n")
 2554     (write _test-input-stream "    var y: int\n")
 2555     (write _test-input-stream "  }\n")
 2556     (write _test-input-stream "  var x: int\n")
 2557     (write _test-input-stream "  increment x\n")
 2558     (write _test-input-stream "}\n")
 2559     # convert
 2560     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2561     (flush _test-output-buffered-file)
 2562 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2568     # check output
 2569     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-mem-after-block/0")
 2570     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-mem-after-block/1")
 2571     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-mem-after-block/2")
 2572     (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")
 2573     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-mem-after-block/4")
 2574     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-mem-after-block/5")
 2575     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-local-var-in-mem-after-block/6")
 2576     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-local-var-in-mem-after-block/7")
 2577     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-local-var-in-mem-after-block/8")
 2578     (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")
 2579     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-local-var-in-mem-after-block/10")
 2580     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-local-var-in-mem-after-block/11")
 2581     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-in-mem-after-block/12")
 2582     (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")
 2583     (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")
 2584     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-mem-after-block/15")
 2585     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-mem-after-block/16")
 2586     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-mem-after-block/17")
 2587     (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")
 2588     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-mem-after-block/19")
 2589     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-mem-after-block/20")
 2590     # . epilogue
 2591     89/<- %esp 5/r32/ebp
 2592     5d/pop-to-ebp
 2593     c3/return
 2594 
 2595 test-convert-function-with-local-var-in-named-block:
 2596     # . prologue
 2597     55/push-ebp
 2598     89/<- %ebp 4/r32/esp
 2599     # setup
 2600     (clear-stream _test-input-stream)
 2601     (clear-stream $_test-input-buffered-file->buffer)
 2602     (clear-stream _test-output-stream)
 2603     (clear-stream $_test-output-buffered-file->buffer)
 2604     #
 2605     (write _test-input-stream "fn foo {\n")
 2606     (write _test-input-stream "  $bar: {\n")
 2607     (write _test-input-stream "    var x: int\n")
 2608     (write _test-input-stream "    increment x\n")
 2609     (write _test-input-stream "  }\n")
 2610     (write _test-input-stream "}\n")
 2611     # convert
 2612     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2613     (flush _test-output-buffered-file)
 2614 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2620     # check output
 2621     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-named-block/0")
 2622     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-named-block/1")
 2623     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-named-block/2")
 2624     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-named-block/3")
 2625     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-named-block/4")
 2626     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-named-block/5")
 2627     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-local-var-in-named-block/6")
 2628     (check-next-stream-line-equal _test-output-stream "$bar:loop:"              "F - test-convert-function-with-local-var-in-named-block/7")
 2629     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-local-var-in-named-block/8")
 2630     (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")
 2631     (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")
 2632     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-local-var-in-named-block/11")
 2633     (check-next-stream-line-equal _test-output-stream "$bar:break:"             "F - test-convert-function-with-local-var-in-named-block/12")
 2634     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-named-block/13")
 2635     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-named-block/14")
 2636     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-named-block/15")
 2637     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-named-block/16")
 2638     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-named-block/17")
 2639     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-named-block/18")
 2640     # . epilogue
 2641     89/<- %esp 5/r32/ebp
 2642     5d/pop-to-ebp
 2643     c3/return
 2644 
 2645 test-unknown-variable-in-named-block:
 2646     # . prologue
 2647     55/push-ebp
 2648     89/<- %ebp 4/r32/esp
 2649     # setup
 2650     (clear-stream _test-input-stream)
 2651     (clear-stream $_test-input-buffered-file->buffer)
 2652     (clear-stream _test-output-stream)
 2653     (clear-stream $_test-output-buffered-file->buffer)
 2654     (clear-stream _test-error-stream)
 2655     (clear-stream $_test-error-buffered-file->buffer)
 2656     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2657     68/push 0/imm32
 2658     68/push 0/imm32
 2659     89/<- %edx 4/r32/esp
 2660     (tailor-exit-descriptor %edx 0x10)
 2661     #
 2662     (write _test-input-stream "fn foo {\n")
 2663     (write _test-input-stream "  $a: {\n")
 2664     (write _test-input-stream "    compare x, 0\n")
 2665     (write _test-input-stream "  }\n")
 2666     (write _test-input-stream "}\n")
 2667     # convert
 2668     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2669     # registers except esp clobbered at this point
 2670     # restore ed
 2671     89/<- %edx 4/r32/esp
 2672     (flush _test-output-buffered-file)
 2673     (flush _test-error-buffered-file)
 2674 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2680     # check output
 2681     (check-stream-equal _test-output-stream  ""  "F - test-unknown-variable-in-named-block: output should be empty")
 2682     (check-next-stream-line-equal _test-error-stream  "fn foo: unknown variable 'x'"  "F - test-unknown-variable-in-named-block: error message")
 2683     # check that stop(1) was called
 2684     (check-ints-equal *(edx+4) 2 "F - test-unknown-variable-in-named-block: exit status")
 2685     # don't restore from ebp
 2686     81 0/subop/add %esp 8/imm32
 2687     # . epilogue
 2688     5d/pop-to-ebp
 2689     c3/return
 2690 
 2691 test-always-shadow-outermost-reg-vars-in-function:
 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     #
 2701     (write _test-input-stream "fn foo {\n")
 2702     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 2703     (write _test-input-stream "}\n")
 2704     # convert
 2705     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2706     (flush _test-output-buffered-file)
 2707 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2713     # check output
 2714     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-always-shadow-outermost-reg-vars-in-function/0")
 2715     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-always-shadow-outermost-reg-vars-in-function/1")
 2716     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-always-shadow-outermost-reg-vars-in-function/2")
 2717     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-always-shadow-outermost-reg-vars-in-function/3")
 2718     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-always-shadow-outermost-reg-vars-in-function/4")
 2719     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-always-shadow-outermost-reg-vars-in-function/5")
 2720     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-compare-register-with-literal/6")
 2721     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-always-shadow-outermost-reg-vars-in-function/8")
 2722     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-compare-register-with-literal/9")
 2723     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-always-shadow-outermost-reg-vars-in-function/12")
 2724     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-always-shadow-outermost-reg-vars-in-function/13")
 2725     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-always-shadow-outermost-reg-vars-in-function/14")
 2726     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-always-shadow-outermost-reg-vars-in-function/15")
 2727     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-always-shadow-outermost-reg-vars-in-function/16")
 2728     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-always-shadow-outermost-reg-vars-in-function/17")
 2729     # . epilogue
 2730     89/<- %esp 5/r32/ebp
 2731     5d/pop-to-ebp
 2732     c3/return
 2733 
 2734 test-shadow-local:
 2735     # . prologue
 2736     55/push-ebp
 2737     89/<- %ebp 4/r32/esp
 2738     # setup
 2739     (clear-stream _test-input-stream)
 2740     (clear-stream $_test-input-buffered-file->buffer)
 2741     (clear-stream _test-output-stream)
 2742     (clear-stream $_test-output-buffered-file->buffer)
 2743     #
 2744     (write _test-input-stream "fn foo {\n")
 2745     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 2746     (write _test-input-stream "  {\n")
 2747     (write _test-input-stream "    var y/ecx: int <- copy 4\n")
 2748     (write _test-input-stream "  }\n")
 2749     (write _test-input-stream "  x <- increment\n")
 2750     (write _test-input-stream "}\n")
 2751     # convert
 2752     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2753     (flush _test-output-buffered-file)
 2754 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2760     # check output
 2761     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-shadow-local/0")
 2762     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-shadow-local/1")
 2763     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-shadow-local/2")
 2764     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-shadow-local/3")
 2765     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-shadow-local/4")
 2766     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-shadow-local/5")
 2767     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-shadow-local/6")
 2768     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-shadow-local/7")
 2769     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-shadow-local/8")
 2770     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-shadow-local/9")
 2771     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %ecx"  "F - test-shadow-local/10")
 2772     (check-next-stream-line-equal _test-output-stream "      b9/copy-to-ecx 4/imm32"  "F - test-shadow-local/11")
 2773     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %ecx" "F - test-shadow-local/12")
 2774     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-shadow-local/13")
 2775     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-shadow-local/14")
 2776     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-shadow-local/15")
 2777     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-shadow-local/16")
 2778     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-shadow-local/17")
 2779     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-shadow-local/18")
 2780     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-shadow-local/19")
 2781     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-shadow-local/20")
 2782     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-shadow-local/21")
 2783     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-shadow-local/22")
 2784     # . epilogue
 2785     89/<- %esp 5/r32/ebp
 2786     5d/pop-to-ebp
 2787     c3/return
 2788 
 2789 test-shadow-name:
 2790     # . prologue
 2791     55/push-ebp
 2792     89/<- %ebp 4/r32/esp
 2793     # setup
 2794     (clear-stream _test-input-stream)
 2795     (clear-stream $_test-input-buffered-file->buffer)
 2796     (clear-stream _test-output-stream)
 2797     (clear-stream $_test-output-buffered-file->buffer)
 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 "  {\n")
 2802     (write _test-input-stream "    var x/edx: int <- copy 4\n")
 2803     (write _test-input-stream "  }\n")
 2804     (write _test-input-stream "  x <- increment\n")
 2805     (write _test-input-stream "}\n")
 2806     # convert
 2807     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2808     (flush _test-output-buffered-file)
 2809 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2815     # check output
 2816     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-shadow-name/0")
 2817     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-shadow-name/1")
 2818     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-shadow-name/2")
 2819     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-shadow-name/3")
 2820     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-shadow-name/4")
 2821     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-shadow-name/5")
 2822     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-shadow-name/6")
 2823     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-shadow-name/7")
 2824     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-shadow-name/8")
 2825     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-shadow-name/9")
 2826     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %edx"  "F - test-shadow-name/10")
 2827     (check-next-stream-line-equal _test-output-stream "      ba/copy-to-edx 4/imm32"  "F - test-shadow-name/11")
 2828     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %edx" "F - test-shadow-name/12")
 2829     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-shadow-name/13")
 2830     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-shadow-name/14")
 2831     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-shadow-name/15")
 2832     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-shadow-name/16")
 2833     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-shadow-name/17")
 2834     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-shadow-name/18")
 2835     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-shadow-name/19")
 2836     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-shadow-name/20")
 2837     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-shadow-name/21")
 2838     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-shadow-name/22")
 2839     # . epilogue
 2840     89/<- %esp 5/r32/ebp
 2841     5d/pop-to-ebp
 2842     c3/return
 2843 
 2844 test-shadow-name-2:
 2845     # . prologue
 2846     55/push-ebp
 2847     89/<- %ebp 4/r32/esp
 2848     # setup
 2849     (clear-stream _test-input-stream)
 2850     (clear-stream $_test-input-buffered-file->buffer)
 2851     (clear-stream _test-output-stream)
 2852     (clear-stream $_test-output-buffered-file->buffer)
 2853     #
 2854     (write _test-input-stream "fn foo {\n")
 2855     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 2856     (write _test-input-stream "  {\n")
 2857     (write _test-input-stream "    var x/edx: int <- copy 4\n")
 2858     (write _test-input-stream "    var y/ecx: int <- copy 5\n")
 2859     (write _test-input-stream "  }\n")
 2860     (write _test-input-stream "  x <- increment\n")
 2861     (write _test-input-stream "}\n")
 2862     # convert
 2863     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2864     (flush _test-output-buffered-file)
 2865 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2871     # check output
 2872     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-shadow-name-2/0")
 2873     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-shadow-name-2/1")
 2874     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-shadow-name-2/2")
 2875     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-shadow-name-2/3")
 2876     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-shadow-name-2/4")
 2877     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-shadow-name-2/5")
 2878     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-shadow-name-2/6")
 2879     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-shadow-name-2/7")
 2880     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-shadow-name-2/8")
 2881     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-shadow-name-2/9")
 2882     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %edx"  "F - test-shadow-name-2/10")
 2883     (check-next-stream-line-equal _test-output-stream "      ba/copy-to-edx 4/imm32"  "F - test-shadow-name-2/11")
 2884     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %ecx"  "F - test-shadow-name-2/12")
 2885     (check-next-stream-line-equal _test-output-stream "      b9/copy-to-ecx 5/imm32"  "F - test-shadow-name-2/13")
 2886     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %ecx" "F - test-shadow-name-2/14")
 2887     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %edx" "F - test-shadow-name-2/15")
 2888     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-shadow-name-2/16")
 2889     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-shadow-name-2/17")
 2890     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-shadow-name-2/18")
 2891     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-shadow-name-2/19")
 2892     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-shadow-name-2/20")
 2893     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-shadow-name-2/21")
 2894     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-shadow-name-2/22")
 2895     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-shadow-name-2/23")
 2896     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-shadow-name-2/24")
 2897     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-shadow-name-2/25")
 2898     # . epilogue
 2899     89/<- %esp 5/r32/ebp
 2900     5d/pop-to-ebp
 2901     c3/return
 2902 
 2903 test-do-not-spill-same-register-in-block:
 2904     # . prologue
 2905     55/push-ebp
 2906     89/<- %ebp 4/r32/esp
 2907     # setup
 2908     (clear-stream _test-input-stream)
 2909     (clear-stream $_test-input-buffered-file->buffer)
 2910     (clear-stream _test-output-stream)
 2911     (clear-stream $_test-output-buffered-file->buffer)
 2912     #
 2913     (write _test-input-stream "fn foo {\n")
 2914     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 2915     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
 2916     (write _test-input-stream "  y <- increment\n")
 2917     (write _test-input-stream "}\n")
 2918     # convert
 2919     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2920     (flush _test-output-buffered-file)
 2921 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2927     # check output
 2928     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-do-not-spill-same-register-in-block/0")
 2929     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-do-not-spill-same-register-in-block/1")
 2930     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-do-not-spill-same-register-in-block/2")
 2931     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-do-not-spill-same-register-in-block/3")
 2932     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-do-not-spill-same-register-in-block/4")
 2933     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-do-not-spill-same-register-in-block/5")
 2934     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-do-not-spill-same-register-in-block/6")
 2935     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-do-not-spill-same-register-in-block/7")
 2936     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 4/imm32"  "F - test-do-not-spill-same-register-in-block/8")
 2937     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-do-not-spill-same-register-in-block/9")
 2938     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-do-not-spill-same-register-in-block/10")
 2939     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-do-not-spill-same-register-in-block/11")
 2940     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-do-not-spill-same-register-in-block/12")
 2941     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-do-not-spill-same-register-in-block/13")
 2942     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-do-not-spill-same-register-in-block/14")
 2943     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-do-not-spill-same-register-in-block/15")
 2944     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-do-not-spill-same-register-in-block/16")
 2945     # . epilogue
 2946     89/<- %esp 5/r32/ebp
 2947     5d/pop-to-ebp
 2948     c3/return
 2949 
 2950 test-spill-different-register-in-block:
 2951     # . prologue
 2952     55/push-ebp
 2953     89/<- %ebp 4/r32/esp
 2954     # setup
 2955     (clear-stream _test-input-stream)
 2956     (clear-stream $_test-input-buffered-file->buffer)
 2957     (clear-stream _test-output-stream)
 2958     (clear-stream $_test-output-buffered-file->buffer)
 2959     #
 2960     (write _test-input-stream "fn foo {\n")
 2961     (write _test-input-stream "  var x/eax: int <- copy 3\n")
 2962     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
 2963     (write _test-input-stream "  y <- increment\n")
 2964     (write _test-input-stream "}\n")
 2965     # convert
 2966     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2967     (flush _test-output-buffered-file)
 2968 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2974     # check output
 2975     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-spill-different-register-in-block/0")
 2976     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-spill-different-register-in-block/1")
 2977     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-spill-different-register-in-block/2")
 2978     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-spill-different-register-in-block/3")
 2979     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-spill-different-register-in-block/4")
 2980     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-spill-different-register-in-block/5")
 2981     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-spill-different-register-in-block/6")
 2982     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 3/imm32"  "F - test-spill-different-register-in-block/7")
 2983     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-spill-different-register-in-block/8")
 2984     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 4/imm32"  "F - test-spill-different-register-in-block/9")
 2985     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-spill-different-register-in-block/10")
 2986     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-spill-different-register-in-block/11")
 2987     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-spill-different-register-in-block/12")
 2988     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-spill-different-register-in-block/13")
 2989     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-spill-different-register-in-block/14")
 2990     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-spill-different-register-in-block/15")
 2991     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-spill-different-register-in-block/16")
 2992     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-spill-different-register-in-block/17")
 2993     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-spill-different-register-in-block/18")
 2994     # . epilogue
 2995     89/<- %esp 5/r32/ebp
 2996     5d/pop-to-ebp
 2997     c3/return
 2998 
 2999 test-convert-function-with-branches-in-block:
 3000     # . prologue
 3001     55/push-ebp
 3002     89/<- %ebp 4/r32/esp
 3003     # setup
 3004     (clear-stream _test-input-stream)
 3005     (clear-stream $_test-input-buffered-file->buffer)
 3006     (clear-stream _test-output-stream)
 3007     (clear-stream $_test-output-buffered-file->buffer)
 3008     #
 3009     (write _test-input-stream "fn foo x: int {\n")
 3010     (write _test-input-stream "  {\n")
 3011     (write _test-input-stream "    break-if->=\n")
 3012     (write _test-input-stream "    loop-if-addr<\n")
 3013     (write _test-input-stream "    increment x\n")
 3014     (write _test-input-stream "    loop\n")
 3015     (write _test-input-stream "  }\n")
 3016     (write _test-input-stream "}\n")
 3017     # convert
 3018     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3019     (flush _test-output-buffered-file)
 3020 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3026     # check output
 3027     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-in-block/0")
 3028     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-in-block/1")
 3029     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-in-block/2")
 3030     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-in-block/3")
 3031     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-in-block/4")
 3032     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-in-block/5")
 3033     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-in-block/6")
 3034     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-branches-in-block/7")
 3035     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-block/8")
 3036     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-in-block/9")
 3037     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-with-branches-in-block/10")
 3038     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-block/11")
 3039     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-block/12")
 3040     (check-next-stream-line-equal _test-output-stream "        0f 83/jump-if-addr>= break/disp32"  "F - test-convert-function-with-branches-in-block/13")
 3041     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:loop/disp32"  "F - test-convert-function-with-branches-in-block/14")
 3042     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-block/15")
 3043     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0x00000008)"  "F - test-convert-function-with-branches-in-block/16")
 3044     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"  "F - test-convert-function-with-branches-in-block/17")
 3045     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-in-block/18")
 3046     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-branches-in-block/19")
 3047     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-in-block/20")
 3048     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-in-block/21")
 3049     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-in-block/22")
 3050     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-in-block/23")
 3051     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-in-block/24")
 3052     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-in-block/25")
 3053     # . epilogue
 3054     89/<- %esp 5/r32/ebp
 3055     5d/pop-to-ebp
 3056     c3/return
 3057 
 3058 test-convert-function-with-branches-in-block-2:
 3059     # . prologue
 3060     55/push-ebp
 3061     89/<- %ebp 4/r32/esp
 3062     # setup
 3063     (clear-stream _test-input-stream)
 3064     (clear-stream $_test-input-buffered-file->buffer)
 3065     (clear-stream _test-output-stream)
 3066     (clear-stream $_test-output-buffered-file->buffer)
 3067     #
 3068     (write _test-input-stream "fn foo x: int {\n")
 3069     (write _test-input-stream "  {\n")
 3070     (write _test-input-stream "    break-if->=\n")
 3071     (write _test-input-stream "    loop-if-float<\n")
 3072     (write _test-input-stream "    increment x\n")
 3073     (write _test-input-stream "    loop\n")
 3074     (write _test-input-stream "  }\n")
 3075     (write _test-input-stream "}\n")
 3076     # convert
 3077     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3078     (flush _test-output-buffered-file)
 3079 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3085     # check output
 3086     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-in-block/0")
 3087     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-in-block/1")
 3088     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-in-block/2")
 3089     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-in-block/3")
 3090     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-in-block/4")
 3091     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-in-block/5")
 3092     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-in-block/6")
 3093     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-branches-in-block/7")
 3094     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-block/8")
 3095     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-in-block/9")
 3096     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-with-branches-in-block/10")
 3097     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-block/11")
 3098     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-block/12")
 3099     (check-next-stream-line-equal _test-output-stream "        0f 83/jump-if-addr>= break/disp32"  "F - test-convert-function-with-branches-in-block/13")
 3100     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:loop/disp32"  "F - test-convert-function-with-branches-in-block/14")
 3101     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-block/15")
 3102     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0x00000008)"  "F - test-convert-function-with-branches-in-block/16")
 3103     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"  "F - test-convert-function-with-branches-in-block/17")
 3104     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-in-block/18")
 3105     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-branches-in-block/19")
 3106     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-in-block/20")
 3107     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-in-block/21")
 3108     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-in-block/22")
 3109     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-in-block/23")
 3110     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-in-block/24")
 3111     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-in-block/25")
 3112     # . epilogue
 3113     89/<- %esp 5/r32/ebp
 3114     5d/pop-to-ebp
 3115     c3/return
 3116 
 3117 test-convert-function-with-branches-in-named-block:
 3118     # . prologue
 3119     55/push-ebp
 3120     89/<- %ebp 4/r32/esp
 3121     # setup
 3122     (clear-stream _test-input-stream)
 3123     (clear-stream $_test-input-buffered-file->buffer)
 3124     (clear-stream _test-output-stream)
 3125     (clear-stream $_test-output-buffered-file->buffer)
 3126     #
 3127     (write _test-input-stream "fn foo x: int {\n")
 3128     (write _test-input-stream "  $bar: {\n")
 3129     (write _test-input-stream "    break-if->= $bar\n")
 3130     (write _test-input-stream "    loop-if-addr< $bar\n")
 3131     (write _test-input-stream "    increment x\n")
 3132     (write _test-input-stream "    loop\n")
 3133     (write _test-input-stream "  }\n")
 3134     (write _test-input-stream "}\n")
 3135     # convert
 3136     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3137     (flush _test-output-buffered-file)
 3138 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3144     # check output
 3145     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-in-named-block/0")
 3146     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-in-named-block/1")
 3147     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-in-named-block/2")
 3148     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-in-named-block/3")
 3149     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-in-named-block/4")
 3150     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-in-named-block/5")
 3151     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-in-named-block/6")
 3152     (check-next-stream-line-equal _test-output-stream "$bar:loop:"              "F - test-convert-function-with-branches-in-named-block/7")
 3153     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-named-block/8")
 3154     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-in-named-block/9")
 3155     (check-next-stream-line-equal _test-output-stream "        e9/jump $bar:break/disp32"  "F - test-convert-function-with-branches-in-named-block/10")
 3156     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-named-block/11")
 3157     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-named-block/12")
 3158     (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")
 3159     (check-next-stream-line-equal _test-output-stream "        e9/jump $bar:loop/disp32"  "F - test-convert-function-with-branches-in-named-block/14")
 3160     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-named-block/15")
 3161     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0x00000008)"  "F - test-convert-function-with-branches-in-named-block/16")
 3162     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"   "F - test-convert-function-with-branches-in-named-block/17")
 3163     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-in-named-block/18")
 3164     (check-next-stream-line-equal _test-output-stream "$bar:break:"             "F - test-convert-function-with-branches-in-named-block/19")
 3165     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-in-named-block/20")
 3166     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-in-named-block/21")
 3167     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-in-named-block/22")
 3168     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-in-named-block/23")
 3169     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-in-named-block/24")
 3170     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-in-named-block/25")
 3171     # . epilogue
 3172     89/<- %esp 5/r32/ebp
 3173     5d/pop-to-ebp
 3174     c3/return
 3175 
 3176 test-convert-function-with-var-in-nested-block:
 3177     # . prologue
 3178     55/push-ebp
 3179     89/<- %ebp 4/r32/esp
 3180     # setup
 3181     (clear-stream _test-input-stream)
 3182     (clear-stream $_test-input-buffered-file->buffer)
 3183     (clear-stream _test-output-stream)
 3184     (clear-stream $_test-output-buffered-file->buffer)
 3185     #
 3186     (write _test-input-stream "fn foo x: int {\n")
 3187     (write _test-input-stream "  {\n")
 3188     (write _test-input-stream "    {\n")
 3189     (write _test-input-stream "      var x: int\n")
 3190     (write _test-input-stream "      increment x\n")
 3191     (write _test-input-stream "    }\n")
 3192     (write _test-input-stream "  }\n")
 3193     (write _test-input-stream "}\n")
 3194     # convert
 3195     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3196     (flush _test-output-buffered-file)
 3197 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3203     # check output
 3204     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-var-in-nested-block/0")
 3205     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-var-in-nested-block/1")
 3206     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-var-in-nested-block/2")
 3207     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-var-in-nested-block/3")
 3208     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-var-in-nested-block/4")
 3209     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-var-in-nested-block/5")
 3210     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-var-in-nested-block/6")
 3211     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-var-in-nested-block/7")
 3212     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-var-in-nested-block/8")
 3213     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-var-in-nested-block/9")
 3214     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-var-in-nested-block/10")
 3215     (check-next-stream-line-equal _test-output-stream "        ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-var-in-nested-block/11")
 3216     (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")
 3217     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-var-in-nested-block/13")
 3218     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-var-in-nested-block/14")
 3219     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-var-in-nested-block/15")
 3220     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-var-in-nested-block/16")
 3221     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-var-in-nested-block/17")
 3222     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-var-in-nested-block/18")
 3223     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-var-in-nested-block/19")
 3224     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-var-in-nested-block/20")
 3225     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-var-in-nested-block/21")
 3226     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-var-in-nested-block/22")
 3227     # . epilogue
 3228     89/<- %esp 5/r32/ebp
 3229     5d/pop-to-ebp
 3230     c3/return
 3231 
 3232 test-convert-function-with-multiple-vars-in-nested-blocks:
 3233     # . prologue
 3234     55/push-ebp
 3235     89/<- %ebp 4/r32/esp
 3236     # setup
 3237     (clear-stream _test-input-stream)
 3238     (clear-stream $_test-input-buffered-file->buffer)
 3239     (clear-stream _test-output-stream)
 3240     (clear-stream $_test-output-buffered-file->buffer)
 3241     #
 3242     (write _test-input-stream "fn foo x: int {\n")
 3243     (write _test-input-stream "  {\n")
 3244     (write _test-input-stream "    var x/eax: int <- copy 0\n")
 3245     (write _test-input-stream "    {\n")
 3246     (write _test-input-stream "      var y: int\n")
 3247     (write _test-input-stream "      x <- add y\n")
 3248     (write _test-input-stream "    }\n")
 3249     (write _test-input-stream "  }\n")
 3250     (write _test-input-stream "}\n")
 3251     # convert
 3252     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3253     (flush _test-output-buffered-file)
 3254 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3260     # check output
 3261     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-multiple-vars-in-nested-blocks/0")
 3262     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-multiple-vars-in-nested-blocks/1")
 3263     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-multiple-vars-in-nested-blocks/2")
 3264     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/3")
 3265     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-multiple-vars-in-nested-blocks/4")
 3266     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/5")
 3267     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-multiple-vars-in-nested-blocks/6")
 3268     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/7")
 3269     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %eax"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/8")
 3270     (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")
 3271     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-multiple-vars-in-nested-blocks/10")
 3272     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/11")
 3273     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-multiple-vars-in-nested-blocks/12")
 3274     (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")
 3275     (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")
 3276     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-multiple-vars-in-nested-blocks/15")
 3277     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/16")
 3278     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %eax"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/17")
 3279     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-multiple-vars-in-nested-blocks/18")
 3280     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/19")
 3281     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-multiple-vars-in-nested-blocks/20")
 3282     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/21")
 3283     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-multiple-vars-in-nested-blocks/22")
 3284     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/23")
 3285     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-multiple-vars-in-nested-blocks/24")
 3286     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-multiple-vars-in-nested-blocks/25")
 3287     # . epilogue
 3288     89/<- %esp 5/r32/ebp
 3289     5d/pop-to-ebp
 3290     c3/return
 3291 
 3292 test-convert-function-with-branches-and-local-vars:
 3293     # A conditional 'break' after a 'var' in a block is converted into a
 3294     # nested block that performs all necessary cleanup before jumping. This
 3295     # results in some ugly code duplication.
 3296     # . prologue
 3297     55/push-ebp
 3298     89/<- %ebp 4/r32/esp
 3299     # setup
 3300     (clear-stream _test-input-stream)
 3301     (clear-stream $_test-input-buffered-file->buffer)
 3302     (clear-stream _test-output-stream)
 3303     (clear-stream $_test-output-buffered-file->buffer)
 3304     #
 3305     (write _test-input-stream "fn foo {\n")
 3306     (write _test-input-stream "  {\n")
 3307     (write _test-input-stream "    var x: int\n")
 3308     (write _test-input-stream "    break-if->=\n")
 3309     (write _test-input-stream "    increment x\n")
 3310     (write _test-input-stream "  }\n")
 3311     (write _test-input-stream "}\n")
 3312     # convert
 3313     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3314     (flush _test-output-buffered-file)
 3315 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3321     # check output
 3322     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-and-local-vars/0")
 3323     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-and-local-vars/1")
 3324     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-and-local-vars/2")
 3325     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-and-local-vars/3")
 3326     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-and-local-vars/4")
 3327     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-and-local-vars/5")
 3328     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-and-local-vars/6")
 3329     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-branches-and-local-vars/7")
 3330     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-branches-and-local-vars/8")
 3331     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-and-local-vars/9")
 3332     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-and-local-vars/10")
 3333     (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")
 3334     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-with-branches-and-local-vars/12")
 3335     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-and-local-vars/13")
 3336     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-branches-and-local-vars/14")
 3337     (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")
 3338     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-and-local-vars/16")
 3339     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-branches-and-local-vars/17")
 3340     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-and-local-vars/18")
 3341     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-and-local-vars/19")
 3342     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-and-local-vars/20")
 3343     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-and-local-vars/21")
 3344     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-and-local-vars/22")
 3345     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-and-local-vars/23")
 3346     # . epilogue
 3347     89/<- %esp 5/r32/ebp
 3348     5d/pop-to-ebp
 3349     c3/return
 3350 
 3351 test-convert-function-with-conditional-loops-and-local-vars:
 3352     # A conditional 'loop' after a 'var' in a block is converted into a nested
 3353     # block that performs all necessary cleanup before jumping. This results
 3354     # in some ugly code duplication.
 3355     # . prologue
 3356     55/push-ebp
 3357     89/<- %ebp 4/r32/esp
 3358     # setup
 3359     (clear-stream _test-input-stream)
 3360     (clear-stream $_test-input-buffered-file->buffer)
 3361     (clear-stream _test-output-stream)
 3362     (clear-stream $_test-output-buffered-file->buffer)
 3363     #
 3364     (write _test-input-stream "fn foo {\n")
 3365     (write _test-input-stream "  {\n")
 3366     (write _test-input-stream "    var x: int\n")
 3367     (write _test-input-stream "    loop-if->=\n")
 3368     (write _test-input-stream "    increment x\n")
 3369     (write _test-input-stream "  }\n")
 3370     (write _test-input-stream "}\n")
 3371     # convert
 3372     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3373     (flush _test-output-buffered-file)
 3374 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3380     # check output
 3381     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-conditional-loops-and-local-vars/0")
 3382     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-conditional-loops-and-local-vars/1")
 3383     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-conditional-loops-and-local-vars/2")
 3384     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-conditional-loops-and-local-vars/3")
 3385     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-conditional-loops-and-local-vars/4")
 3386     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-conditional-loops-and-local-vars/5")
 3387     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-conditional-loops-and-local-vars/6")
 3388     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-conditional-loops-and-local-vars/7")
 3389     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-conditional-loops-and-local-vars/8")
 3390     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-conditional-loops-and-local-vars/9")
 3391     (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")
 3392     (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")
 3393     (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")
 3394     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-conditional-loops-and-local-vars/13")
 3395     (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")
 3396     (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")
 3397     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-conditional-loops-and-local-vars/16")
 3398     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-conditional-loops-and-local-vars/17")
 3399     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-conditional-loops-and-local-vars/18")
 3400     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-conditional-loops-and-local-vars/19")
 3401     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-conditional-loops-and-local-vars/20")
 3402     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-conditional-loops-and-local-vars/21")
 3403     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-conditional-loops-and-local-vars/22")
 3404     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-conditional-loops-and-local-vars/23")
 3405     # . epilogue
 3406     89/<- %esp 5/r32/ebp
 3407     5d/pop-to-ebp
 3408     c3/return
 3409 
 3410 test-convert-function-with-unconditional-loops-and-local-vars:
 3411     # An unconditional 'loop' after a 'var' in a block is emitted _after_ the
 3412     # regular block cleanup. Any instructions after 'loop' are dead and
 3413     # therefore skipped.
 3414     # . prologue
 3415     55/push-ebp
 3416     89/<- %ebp 4/r32/esp
 3417     # setup
 3418     (clear-stream _test-input-stream)
 3419     (clear-stream $_test-input-buffered-file->buffer)
 3420     (clear-stream _test-output-stream)
 3421     (clear-stream $_test-output-buffered-file->buffer)
 3422     #
 3423     (write _test-input-stream "fn foo {\n")
 3424     (write _test-input-stream "  {\n")
 3425     (write _test-input-stream "    var x: int\n")
 3426     (write _test-input-stream "    loop\n")
 3427     (write _test-input-stream "    increment x\n")
 3428     (write _test-input-stream "  }\n")
 3429     (write _test-input-stream "}\n")
 3430     # convert
 3431     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3432     (flush _test-output-buffered-file)
 3433 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3439     # check output
 3440     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-unconditional-loops-and-local-vars/0")
 3441     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-unconditional-loops-and-local-vars/1")
 3442     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-unconditional-loops-and-local-vars/2")
 3443     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-unconditional-loops-and-local-vars/3")
 3444     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-unconditional-loops-and-local-vars/4")
 3445     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-unconditional-loops-and-local-vars/5")
 3446     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-unconditional-loops-and-local-vars/6")
 3447     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-unconditional-loops-and-local-vars/7")
 3448     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-unconditional-loops-and-local-vars/8")
 3449     (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")
 3450     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"  "F - test-convert-function-with-unconditional-loops-and-local-vars/10")
 3451     # not emitted:                                           ff 0/subop/increment *(ebp+0xfffffffc)
 3452     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-unconditional-loops-and-local-vars/11")
 3453     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-unconditional-loops-and-local-vars/12")
 3454     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-unconditional-loops-and-local-vars/13")
 3455     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-unconditional-loops-and-local-vars/14")
 3456     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-unconditional-loops-and-local-vars/15")
 3457     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-unconditional-loops-and-local-vars/16")
 3458     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-unconditional-loops-and-local-vars/17")
 3459     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-unconditional-loops-and-local-vars/18")
 3460     # . epilogue
 3461     89/<- %esp 5/r32/ebp
 3462     5d/pop-to-ebp
 3463     c3/return
 3464 
 3465 test-convert-function-with-branches-and-loops-and-local-vars:
 3466     # . prologue
 3467     55/push-ebp
 3468     89/<- %ebp 4/r32/esp
 3469     # setup
 3470     (clear-stream _test-input-stream)
 3471     (clear-stream $_test-input-buffered-file->buffer)
 3472     (clear-stream _test-output-stream)
 3473     (clear-stream $_test-output-buffered-file->buffer)
 3474     #
 3475     (write _test-input-stream "fn foo {\n")
 3476     (write _test-input-stream "  {\n")
 3477     (write _test-input-stream "    var x: int\n")
 3478     (write _test-input-stream "    break-if->=\n")
 3479     (write _test-input-stream "    increment x\n")
 3480     (write _test-input-stream "    loop\n")
 3481     (write _test-input-stream "  }\n")
 3482     (write _test-input-stream "}\n")
 3483     # convert
 3484     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3485     (flush _test-output-buffered-file)
 3486 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3492     # check output
 3493     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-and-loops-and-local-vars/0")
 3494     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-and-loops-and-local-vars/1")
 3495     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-and-loops-and-local-vars/2")
 3496     (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")
 3497     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-and-loops-and-local-vars/4")
 3498     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-and-loops-and-local-vars/5")
 3499     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-and-loops-and-local-vars/6")
 3500     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-branches-and-loops-and-local-vars/7")
 3501     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-branches-and-loops-and-local-vars/8")
 3502     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-and-loops-and-local-vars/9")
 3503     (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")
 3504     (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")
 3505     (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")
 3506     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-and-loops-and-local-vars/13")
 3507     (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")
 3508     (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")
 3509     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"  "F - test-convert-function-with-branches-and-loops-and-local-vars/16")
 3510     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-and-loops-and-local-vars/17")
 3511     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-branches-and-loops-and-local-vars/18")
 3512     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-and-loops-and-local-vars/19")
 3513     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-and-loops-and-local-vars/20")
 3514     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-and-loops-and-local-vars/21")
 3515     (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")
 3516     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-and-loops-and-local-vars/23")
 3517     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-and-loops-and-local-vars/24")
 3518     # . epilogue
 3519     89/<- %esp 5/r32/ebp
 3520     5d/pop-to-ebp
 3521     c3/return
 3522 
 3523 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars:
 3524     # . prologue
 3525     55/push-ebp
 3526     89/<- %ebp 4/r32/esp
 3527     # setup
 3528     (clear-stream _test-input-stream)
 3529     (clear-stream $_test-input-buffered-file->buffer)
 3530     (clear-stream _test-output-stream)
 3531     (clear-stream $_test-output-buffered-file->buffer)
 3532     #
 3533     (write _test-input-stream "fn foo {\n")
 3534     (write _test-input-stream "  a: {\n")
 3535     (write _test-input-stream "    var x: int\n")
 3536     (write _test-input-stream "    {\n")
 3537     (write _test-input-stream "      var y: int\n")
 3538     (write _test-input-stream "      break-if->= a\n")
 3539     (write _test-input-stream "      increment x\n")
 3540     (write _test-input-stream "      loop\n")
 3541     (write _test-input-stream "    }\n")
 3542     (write _test-input-stream "  }\n")
 3543     (write _test-input-stream "}\n")
 3544     # convert
 3545     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3546     (flush _test-output-buffered-file)
 3547 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3553     # check output
 3554     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/0")
 3555     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/1")
 3556     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/2")
 3557     (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")
 3558     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/4")
 3559     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/5")
 3560     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/6")
 3561     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/7")
 3562     (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")
 3563     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/9")
 3564     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/10")
 3565     (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")
 3566     (check-next-stream-line-equal _test-output-stream "        {"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/12")
 3567     (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")
 3568     (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")
 3569     (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")
 3570     (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")
 3571     (check-next-stream-line-equal _test-output-stream "        }"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/17")
 3572     (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")
 3573     (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")
 3574     (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")
 3575     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/21")
 3576     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/22")
 3577     (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")
 3578     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/24")
 3579     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/25")
 3580     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/26")
 3581     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/27")
 3582     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/28")
 3583     (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")
 3584     (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")
 3585     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/31")
 3586     # . epilogue
 3587     89/<- %esp 5/r32/ebp
 3588     5d/pop-to-ebp
 3589     c3/return
 3590 
 3591 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2:
 3592     # . prologue
 3593     55/push-ebp
 3594     89/<- %ebp 4/r32/esp
 3595     # setup
 3596     (clear-stream _test-input-stream)
 3597     (clear-stream $_test-input-buffered-file->buffer)
 3598     (clear-stream _test-output-stream)
 3599     (clear-stream $_test-output-buffered-file->buffer)
 3600     # non-local conditional branch from a block without a local variable,
 3601     # unwinding a local on the stack
 3602     (write _test-input-stream "fn foo {\n")
 3603     (write _test-input-stream "  a: {\n")
 3604     (write _test-input-stream "    var x: int\n")
 3605     (write _test-input-stream "    {\n")
 3606     (write _test-input-stream "      break-if->= a\n")
 3607     (write _test-input-stream "    }\n")
 3608     (write _test-input-stream "  }\n")
 3609     (write _test-input-stream "}\n")
 3610     # convert
 3611     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3612     (flush _test-output-buffered-file)
 3613 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3619     # check output
 3620     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/0")
 3621     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/1")
 3622     (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")
 3623     (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")
 3624     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/4")
 3625     (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")
 3626     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/6")
 3627     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/7")
 3628     (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")
 3629     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/9")
 3630     (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")
 3631     (check-next-stream-line-equal _test-output-stream "        {"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/11")
 3632     (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")
 3633     (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")
 3634     (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")
 3635     (check-next-stream-line-equal _test-output-stream "        }"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/15")
 3636     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/16")
 3637     (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")
 3638     (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")
 3639     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/19")
 3640     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/20")
 3641     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/21")
 3642     (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")
 3643     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/23")
 3644     (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")
 3645     (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")
 3646     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/26")
 3647     # . epilogue
 3648     89/<- %esp 5/r32/ebp
 3649     5d/pop-to-ebp
 3650     c3/return
 3651 
 3652 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3:
 3653     # . prologue
 3654     55/push-ebp
 3655     89/<- %ebp 4/r32/esp
 3656     # setup
 3657     (clear-stream _test-input-stream)
 3658     (clear-stream $_test-input-buffered-file->buffer)
 3659     (clear-stream _test-output-stream)
 3660     (clear-stream $_test-output-buffered-file->buffer)
 3661     # non-local unconditional branch from a block without a local variable,
 3662     # unwinding a local on the stack
 3663     (write _test-input-stream "fn foo {\n")
 3664     (write _test-input-stream "  a: {\n")
 3665     (write _test-input-stream "    var x: int\n")
 3666     (write _test-input-stream "    {\n")
 3667     (write _test-input-stream "      break a\n")
 3668     (write _test-input-stream "    }\n")
 3669     (write _test-input-stream "  }\n")
 3670     (write _test-input-stream "}\n")
 3671     # convert
 3672     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3673     (flush _test-output-buffered-file)
 3674 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3680     # check output
 3681     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/0")
 3682     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/1")
 3683     (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")
 3684     (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")
 3685     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/4")
 3686     (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")
 3687     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/6")
 3688     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/7")
 3689     (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")
 3690     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/9")
 3691     (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")
 3692     (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")
 3693     (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")
 3694     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/14")
 3695     (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")
 3696     (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")
 3697     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/17")
 3698     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/18")
 3699     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/19")
 3700     (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")
 3701     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/21")
 3702     (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")
 3703     (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")
 3704     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/24")
 3705     # . epilogue
 3706     89/<- %esp 5/r32/ebp
 3707     5d/pop-to-ebp
 3708     c3/return
 3709 
 3710 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4:
 3711     # . prologue
 3712     55/push-ebp
 3713     89/<- %ebp 4/r32/esp
 3714     # setup
 3715     (clear-stream _test-input-stream)
 3716     (clear-stream $_test-input-buffered-file->buffer)
 3717     (clear-stream _test-output-stream)
 3718     (clear-stream $_test-output-buffered-file->buffer)
 3719     #
 3720     (write _test-input-stream "fn foo {\n")
 3721     (write _test-input-stream "  a: {\n")
 3722     (write _test-input-stream "    var x/esi: int <- copy 0\n")
 3723     (write _test-input-stream "    {\n")
 3724     (write _test-input-stream "      break a\n")
 3725     (write _test-input-stream "    }\n")
 3726     (write _test-input-stream "  }\n")
 3727     (write _test-input-stream "}\n")
 3728     # convert
 3729     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3730     (flush _test-output-buffered-file)
 3731 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3737     # check output
 3738     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/0")
 3739     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/1")
 3740     (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")
 3741     (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")
 3742     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/4")
 3743     (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")
 3744     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/6")
 3745     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/7")
 3746     (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")
 3747     (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")
 3748     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/10")
 3749     (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")
 3750     (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")
 3751     (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")
 3752     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/14")
 3753     (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")
 3754     (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")
 3755     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/17")
 3756     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/18")
 3757     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/19")
 3758     (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")
 3759     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/21")
 3760     (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")
 3761     (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")
 3762     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/24")
 3763     # . epilogue
 3764     89/<- %esp 5/r32/ebp
 3765     5d/pop-to-ebp
 3766     c3/return
 3767 
 3768 test-convert-function-with-nonlocal-unconditional-break-and-local-vars:
 3769     # . prologue
 3770     55/push-ebp
 3771     89/<- %ebp 4/r32/esp
 3772     # setup
 3773     (clear-stream _test-input-stream)
 3774     (clear-stream $_test-input-buffered-file->buffer)
 3775     (clear-stream _test-output-stream)
 3776     (clear-stream $_test-output-buffered-file->buffer)
 3777     #
 3778     (write _test-input-stream "fn foo {\n")
 3779     (write _test-input-stream "  a: {\n")
 3780     (write _test-input-stream "    var x: int\n")
 3781     (write _test-input-stream "    {\n")
 3782     (write _test-input-stream "      var y: int\n")
 3783     (write _test-input-stream "      break a\n")
 3784     (write _test-input-stream "      increment x\n")
 3785     (write _test-input-stream "    }\n")
 3786     (write _test-input-stream "  }\n")
 3787     (write _test-input-stream "}\n")
 3788     # convert
 3789     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3790     (flush _test-output-buffered-file)
 3791 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3797     # check output
 3798     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/0")
 3799     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/1")
 3800     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/2")
 3801     (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")
 3802     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/4")
 3803     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/5")
 3804     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/6")
 3805     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/7")
 3806     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/8")
 3807     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/9")
 3808     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/10")
 3809     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/11")
 3810     (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")
 3811     (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")
 3812     (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")
 3813     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/15")
 3814     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/16")
 3815     (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")
 3816     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/18")
 3817     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/19")
 3818     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/20")
 3819     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/21")
 3820     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/22")
 3821     (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")
 3822     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/24")
 3823     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/25")
 3824     # . epilogue
 3825     89/<- %esp 5/r32/ebp
 3826     5d/pop-to-ebp
 3827     c3/return
 3828 
 3829 test-convert-function-with-unconditional-break-and-local-vars:
 3830     # . prologue
 3831     55/push-ebp
 3832     89/<- %ebp 4/r32/esp
 3833     # setup
 3834     (clear-stream _test-input-stream)
 3835     (clear-stream $_test-input-buffered-file->buffer)
 3836     (clear-stream _test-output-stream)
 3837     (clear-stream $_test-output-buffered-file->buffer)
 3838     #
 3839     (write _test-input-stream "fn foo {\n")
 3840     (write _test-input-stream "  {\n")
 3841     (write _test-input-stream "    var x: int\n")
 3842     (write _test-input-stream "    {\n")
 3843     (write _test-input-stream "      var y: int\n")
 3844     (write _test-input-stream "      break\n")
 3845     (write _test-input-stream "      increment x\n")
 3846     (write _test-input-stream "    }\n")
 3847     (write _test-input-stream "  }\n")
 3848     (write _test-input-stream "}\n")
 3849     # convert
 3850     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3851     (flush _test-output-buffered-file)
 3852 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3858     # check output
 3859     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-unconditional-break-and-local-vars/0")
 3860     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-unconditional-break-and-local-vars/1")
 3861     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-unconditional-break-and-local-vars/2")
 3862     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-unconditional-break-and-local-vars/3")
 3863     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-unconditional-break-and-local-vars/4")
 3864     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-unconditional-break-and-local-vars/5")
 3865     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-unconditional-break-and-local-vars/6")
 3866     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-unconditional-break-and-local-vars/7")
 3867     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-unconditional-break-and-local-vars/8")
 3868     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-unconditional-break-and-local-vars/9")
 3869     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-unconditional-break-and-local-vars/10")
 3870     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-unconditional-break-and-local-vars/11")
 3871     (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")
 3872     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-unconditional-break-and-local-vars/13")
 3873     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-unconditional-break-and-local-vars/14")
 3874     (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")
 3875     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-unconditional-break-and-local-vars/16")
 3876     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-unconditional-break-and-local-vars/17")
 3877     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-unconditional-break-and-local-vars/18")
 3878     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-unconditional-break-and-local-vars/19")
 3879     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-unconditional-break-and-local-vars/20")
 3880     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-unconditional-break-and-local-vars/21")
 3881     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-unconditional-break-and-local-vars/22")
 3882     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-unconditional-break-and-local-vars/23")
 3883     # . epilogue
 3884     89/<- %esp 5/r32/ebp
 3885     5d/pop-to-ebp
 3886     c3/return
 3887 
 3888 test-convert-function-with-nonlocal-unconditional-loop-and-local-vars:
 3889     # . prologue
 3890     55/push-ebp
 3891     89/<- %ebp 4/r32/esp
 3892     # setup
 3893     (clear-stream _test-input-stream)
 3894     (clear-stream $_test-input-buffered-file->buffer)
 3895     (clear-stream _test-output-stream)
 3896     (clear-stream $_test-output-buffered-file->buffer)
 3897     #
 3898     (write _test-input-stream "fn foo {\n")
 3899     (write _test-input-stream "  a: {\n")
 3900     (write _test-input-stream "    var x: int\n")
 3901     (write _test-input-stream "    {\n")
 3902     (write _test-input-stream "      var y: int\n")
 3903     (write _test-input-stream "      loop a\n")
 3904     (write _test-input-stream "      increment x\n")
 3905     (write _test-input-stream "    }\n")
 3906     (write _test-input-stream "  }\n")
 3907     (write _test-input-stream "}\n")
 3908     # convert
 3909     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3910     (flush _test-output-buffered-file)
 3911 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3917     # check output
 3918     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/0")
 3919     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/1")
 3920     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/2")
 3921     (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")
 3922     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/4")
 3923     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/5")
 3924     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/6")
 3925     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/7")
 3926     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/8")
 3927     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/9")
 3928     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/10")
 3929     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/11")
 3930     (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")
 3931     (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")
 3932     (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")
 3933     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/15")
 3934     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/16")
 3935     (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")
 3936     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/18")
 3937     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/19")
 3938     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/20")
 3939     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/21")
 3940     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/22")
 3941     (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")
 3942     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/24")
 3943     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/25")
 3944     # . epilogue
 3945     89/<- %esp 5/r32/ebp
 3946     5d/pop-to-ebp
 3947     c3/return
 3948 
 3949 test-convert-function-with-local-array-var-in-mem:
 3950     # . prologue
 3951     55/push-ebp
 3952     89/<- %ebp 4/r32/esp
 3953     # setup
 3954     (clear-stream _test-input-stream)
 3955     (clear-stream $_test-input-buffered-file->buffer)
 3956     (clear-stream _test-output-stream)
 3957     (clear-stream $_test-output-buffered-file->buffer)
 3958     #
 3959     (write _test-input-stream "fn foo {\n")
 3960     (write _test-input-stream "  var x: (array int 3)\n")
 3961     (write _test-input-stream "}\n")
 3962     # convert
 3963     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3964     (flush _test-output-buffered-file)
 3965 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3971     # check output
 3972     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-array-var-in-mem/0")
 3973     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-array-var-in-mem/1")
 3974     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-array-var-in-mem/2")
 3975     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-array-var-in-mem/3")
 3976     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-array-var-in-mem/4")
 3977     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-array-var-in-mem/5")
 3978     # define x
 3979     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x0000000c)"  "F - test-convert-function-with-local-array-var-in-mem/7")
 3980     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"  "F - test-convert-function-with-local-array-var-in-mem/8")
 3981     # reclaim x
 3982     (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")
 3983     #
 3984     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-array-var-in-mem/10")
 3985     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-array-var-in-mem/11")
 3986     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-array-var-in-mem/12")
 3987     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-array-var-in-mem/13")
 3988     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-array-var-in-mem/14")
 3989     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-array-var-in-mem/15")
 3990     # . epilogue
 3991     89/<- %esp 5/r32/ebp
 3992     5d/pop-to-ebp
 3993     c3/return
 3994 
 3995 test-array-size-in-hex:
 3996     # . prologue
 3997     55/push-ebp
 3998     89/<- %ebp 4/r32/esp
 3999     # setup
 4000     (clear-stream _test-input-stream)
 4001     (clear-stream $_test-input-buffered-file->buffer)
 4002     (clear-stream _test-output-stream)
 4003     (clear-stream $_test-output-buffered-file->buffer)
 4004     (clear-stream _test-error-stream)
 4005     (clear-stream $_test-error-buffered-file->buffer)
 4006     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 4007     68/push 0/imm32
 4008     68/push 0/imm32
 4009     89/<- %edx 4/r32/esp
 4010     (tailor-exit-descriptor %edx 0x10)
 4011     #
 4012     (write _test-input-stream "fn foo {\n")
 4013     (write _test-input-stream "  var x: (array int 10)\n")
 4014     (write _test-input-stream "}\n")
 4015     # convert
 4016     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 4017     # registers except esp clobbered at this point
 4018     # restore ed
 4019     89/<- %edx 4/r32/esp
 4020     (flush _test-output-buffered-file)
 4021     (flush _test-error-buffered-file)
 4022 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4028     # check output
 4029     (check-stream-equal _test-output-stream  ""  "F - test-array-size-in-hex: output should be empty")
 4030     (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")
 4031     # check that stop(1) was called
 4032     (check-ints-equal *(edx+4) 2 "F - test-array-size-in-hex: exit status")
 4033     # don't restore from ebp
 4034     81 0/subop/add %esp 8/imm32
 4035     # . epilogue
 4036     5d/pop-to-ebp
 4037     c3/return
 4038 
 4039 test-convert-function-with-populate:
 4040     # . prologue
 4041     55/push-ebp
 4042     89/<- %ebp 4/r32/esp
 4043     # setup
 4044     (clear-stream _test-input-stream)
 4045     (clear-stream $_test-input-buffered-file->buffer)
 4046     (clear-stream _test-output-stream)
 4047     (clear-stream $_test-output-buffered-file->buffer)
 4048     #
 4049     (write _test-input-stream "fn foo {\n")
 4050     (write _test-input-stream "  var x/ecx: (addr handle array int) <- copy 0\n")
 4051     (write _test-input-stream "  populate x, 7\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-populate/0")
 4064     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-populate/1")
 4065     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-populate/2")
 4066     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-populate/3")
 4067     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-populate/4")
 4068     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-populate/5")
 4069     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-populate/6")
 4070     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-function-with-populate/7")
 4071     (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)
 4072     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-populate/9")
 4073     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-populate/10")
 4074     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-populate/11")
 4075     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-populate/12")
 4076     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-populate/13")
 4077     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-populate/14")
 4078     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-populate/15")
 4079     # . epilogue
 4080     89/<- %esp 5/r32/ebp
 4081     5d/pop-to-ebp
 4082     c3/return
 4083 
 4084 # special-case for size(byte) when allocating array
 4085 test-convert-function-with-local-array-of-bytes-in-mem:
 4086     # . prologue
 4087     55/push-ebp
 4088     89/<- %ebp 4/r32/esp
 4089     # setup
 4090     (clear-stream _test-input-stream)
 4091     (clear-stream $_test-input-buffered-file->buffer)
 4092     (clear-stream _test-output-stream)
 4093     (clear-stream $_test-output-buffered-file->buffer)
 4094     #
 4095     (write _test-input-stream "fn foo {\n")
 4096     (write _test-input-stream "  var x: (array byte 3)\n")
 4097     (write _test-input-stream "}\n")
 4098     # convert
 4099     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4100     (flush _test-output-buffered-file)
 4101 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4107     # check output
 4108     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-array-of-bytes-in-mem/0")
 4109     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-array-of-bytes-in-mem/1")
 4110     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-array-of-bytes-in-mem/2")
 4111     (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")
 4112     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-array-of-bytes-in-mem/4")
 4113     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-array-of-bytes-in-mem/5")
 4114     # define x
 4115     (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")
 4116     (check-next-stream-line-equal _test-output-stream "    68/push 0x00000003/imm32"  "F - test-convert-function-with-local-array-of-bytes-in-mem/8")
 4117     # reclaim x
 4118     (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")
 4119     #
 4120     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-array-of-bytes-in-mem/10")
 4121     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-array-of-bytes-in-mem/11")
 4122     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-array-of-bytes-in-mem/12")
 4123     (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")
 4124     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-array-of-bytes-in-mem/14")
 4125     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-array-of-bytes-in-mem/15")
 4126     # . epilogue
 4127     89/<- %esp 5/r32/ebp
 4128     5d/pop-to-ebp
 4129     c3/return
 4130 
 4131 test-convert-address:
 4132     # . prologue
 4133     55/push-ebp
 4134     89/<- %ebp 4/r32/esp
 4135     # setup
 4136     (clear-stream _test-input-stream)
 4137     (clear-stream $_test-input-buffered-file->buffer)
 4138     (clear-stream _test-output-stream)
 4139     (clear-stream $_test-output-buffered-file->buffer)
 4140     #
 4141     (write _test-input-stream "fn foo {\n")
 4142     (write _test-input-stream "  var a: int\n")
 4143     (write _test-input-stream "  var b/eax: (addr int) <- address a\n")
 4144     (write _test-input-stream "}\n")
 4145     # convert
 4146     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4147     (flush _test-output-buffered-file)
 4148 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4154     # check output
 4155     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-address/0")
 4156     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-address/1")
 4157     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-address/2")
 4158     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-address/3")
 4159     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-address/4")
 4160     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-address/5")
 4161     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-address/6")
 4162     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-address/7")
 4163     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp+0xfffffffc) 0x00000000/r32"  "F - test-convert-address/8")
 4164     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-address/9")
 4165     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-address/10")
 4166     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-address/11")
 4167     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-address/12")
 4168     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-address/13")
 4169     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-address/14")
 4170     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-address/15")
 4171     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-address/16")
 4172     # . epilogue
 4173     89/<- %esp 5/r32/ebp
 4174     5d/pop-to-ebp
 4175     c3/return
 4176 
 4177 test-convert-floating-point-convert:
 4178     # . prologue
 4179     55/push-ebp
 4180     89/<- %ebp 4/r32/esp
 4181     # setup
 4182     (clear-stream _test-input-stream)
 4183     (clear-stream $_test-input-buffered-file->buffer)
 4184     (clear-stream _test-output-stream)
 4185     (clear-stream $_test-output-buffered-file->buffer)
 4186     #
 4187     (write _test-input-stream "fn foo {\n")
 4188     (write _test-input-stream "  var a/eax: int <- copy 0\n")
 4189     (write _test-input-stream "  var b/xmm1: float <- convert a\n")
 4190     (write _test-input-stream "}\n")
 4191     # convert
 4192     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4193     (flush _test-output-buffered-file)
 4194 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4200     # check output
 4201     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-floating-point-convert/0")
 4202     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-floating-point-convert/1")
 4203     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-floating-point-convert/2")
 4204     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-floating-point-convert/3")
 4205     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-floating-point-convert/4")
 4206     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-floating-point-convert/5")
 4207     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-floating-point-convert/6")
 4208     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"  "F - test-convert-floating-point-convert/7")
 4209     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"  "F - test-convert-floating-point-convert/8")
 4210     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 1/x32"  "F - test-convert-floating-point-convert/9")
 4211     (check-next-stream-line-equal _test-output-stream "    f3 0f 2a/convert-to-float %eax 0x00000001/x32"  "F - test-convert-floating-point-convert/10")
 4212     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 1/x32"  "F - test-convert-floating-point-convert/11")
 4213     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-floating-point-convert/12")
 4214     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-floating-point-convert/13")
 4215     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-floating-point-convert/14")
 4216     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-floating-point-convert/15")
 4217     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-floating-point-convert/16")
 4218     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-floating-point-convert/17")
 4219     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-floating-point-convert/18")
 4220     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-floating-point-convert/19")
 4221     # . epilogue
 4222     89/<- %esp 5/r32/ebp
 4223     5d/pop-to-ebp
 4224     c3/return
 4225 
 4226 test-convert-floating-point-convert-2:
 4227     # . prologue
 4228     55/push-ebp
 4229     89/<- %ebp 4/r32/esp
 4230     # setup
 4231     (clear-stream _test-input-stream)
 4232     (clear-stream $_test-input-buffered-file->buffer)
 4233     (clear-stream _test-output-stream)
 4234     (clear-stream $_test-output-buffered-file->buffer)
 4235     #
 4236     (write _test-input-stream "fn foo {\n")
 4237     (write _test-input-stream "  var a/eax: int <- copy 0\n")
 4238     (write _test-input-stream "  var b/xmm1: float <- convert a\n")
 4239     (write _test-input-stream "  a <- convert b\n")
 4240     (write _test-input-stream "}\n")
 4241     # convert
 4242     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4243     (flush _test-output-buffered-file)
 4244 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4250     # check output
 4251     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-floating-point-convert-2/0")
 4252     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-floating-point-convert-2/1")
 4253     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-floating-point-convert-2/2")
 4254     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-floating-point-convert-2/3")
 4255     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-floating-point-convert-2/4")
 4256     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-floating-point-convert-2/5")
 4257     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-floating-point-convert-2/6")
 4258     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"  "F - test-convert-floating-point-convert-2/7")
 4259     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"  "F - test-convert-floating-point-convert-2/8")
 4260     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 1/x32"  "F - test-convert-floating-point-convert-2/9")
 4261     (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")
 4262     (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")
 4263     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 1/x32"  "F - test-convert-floating-point-convert-2/12")
 4264     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-floating-point-convert-2/13")
 4265     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-floating-point-convert-2/14")
 4266     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-floating-point-convert-2/15")
 4267     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-floating-point-convert-2/16")
 4268     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-floating-point-convert-2/17")
 4269     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-floating-point-convert-2/18")
 4270     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-floating-point-convert-2/19")
 4271     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-floating-point-convert-2/20")
 4272     # . epilogue
 4273     89/<- %esp 5/r32/ebp
 4274     5d/pop-to-ebp
 4275     c3/return
 4276 
 4277 test-convert-floating-point-operation:
 4278     # . prologue
 4279     55/push-ebp
 4280     89/<- %ebp 4/r32/esp
 4281     # setup
 4282     (clear-stream _test-input-stream)
 4283     (clear-stream $_test-input-buffered-file->buffer)
 4284     (clear-stream _test-output-stream)
 4285     (clear-stream $_test-output-buffered-file->buffer)
 4286     #
 4287     (write _test-input-stream "fn f {\n")
 4288     (write _test-input-stream "  var m: float\n")
 4289     (write _test-input-stream "  var x/xmm1: float <- copy m\n")
 4290     (write _test-input-stream "  var y/xmm5: float <- copy m\n")
 4291     (write _test-input-stream "  x <- copy y\n")
 4292     (write _test-input-stream "  copy-to m, y\n")
 4293     (write _test-input-stream "  x <- add y\n")
 4294     (write _test-input-stream "  x <- add m\n")
 4295     (write _test-input-stream "  x <- subtract y\n")
 4296     (write _test-input-stream "  x <- subtract m\n")
 4297     (write _test-input-stream "  x <- multiply y\n")
 4298     (write _test-input-stream "  x <- multiply m\n")
 4299     (write _test-input-stream "  x <- divide y\n")
 4300     (write _test-input-stream "  x <- divide m\n")
 4301     (write _test-input-stream "  x <- reciprocal y\n")
 4302     (write _test-input-stream "  x <- reciprocal m\n")
 4303     (write _test-input-stream "  x <- square-root y\n")
 4304     (write _test-input-stream "  x <- square-root m\n")
 4305     (write _test-input-stream "  x <- inverse-square-root y\n")
 4306     (write _test-input-stream "  x <- inverse-square-root m\n")
 4307     (write _test-input-stream "  x <- max y\n")
 4308     (write _test-input-stream "  x <- max m\n")
 4309     (write _test-input-stream "  x <- min y\n")
 4310     (write _test-input-stream "  x <- min m\n")
 4311     (write _test-input-stream "  compare x, y\n")
 4312     (write _test-input-stream "  compare x, m\n")
 4313     (write _test-input-stream "}\n")
 4314     # convert
 4315     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4316     (flush _test-output-buffered-file)
 4317 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4323     # check output
 4324     (check-next-stream-line-equal _test-output-stream "f:"                                                                     "F - test-convert-floating-point-operation/0")
 4325     (check-next-stream-line-equal _test-output-stream "  # . prologue"                                                         "F - test-convert-floating-point-operation/1")
 4326     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                                                          "F - test-convert-floating-point-operation/2")
 4327     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                                                 "F - test-convert-floating-point-operation/3")
 4328     (check-next-stream-line-equal _test-output-stream "  {"                                                                    "F - test-convert-floating-point-operation/4")
 4329     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"                                                    "F - test-convert-floating-point-operation/5")
 4330     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"                                                    "F - test-convert-floating-point-operation/6")
 4331     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"                                   "F - test-convert-floating-point-operation/7")
 4332     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 1/x32"                                             "F - test-convert-floating-point-operation/8")
 4333     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/copy *(ebp+0xfffffffc) 0x00000001/x32"                     "F - test-convert-floating-point-operation/9")
 4334     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"                                   "F - test-convert-floating-point-operation/10")
 4335     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 5/x32"                                             "F - test-convert-floating-point-operation/11")
 4336     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/copy *(ebp+0xfffffffc) 0x00000005/x32"                     "F - test-convert-floating-point-operation/12")
 4337     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/copy %xmm1 0x00000005/x32"                                 "F - test-convert-floating-point-operation/13")
 4338     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/copy *(ebp+0xfffffffc) 0x00000005/x32"                     "F - test-convert-floating-point-operation/14")
 4339     (check-next-stream-line-equal _test-output-stream "    f3 0f 58/add %xmm5 0x00000001/x32"                                  "F - test-convert-floating-point-operation/15")
 4340     (check-next-stream-line-equal _test-output-stream "    f3 0f 58/add *(ebp+0xfffffffc) 0x00000001/x32"                      "F - test-convert-floating-point-operation/16")
 4341     (check-next-stream-line-equal _test-output-stream "    f3 0f 5c/subtract %xmm5 0x00000001/x32"                             "F - test-convert-floating-point-operation/17")
 4342     (check-next-stream-line-equal _test-output-stream "    f3 0f 5c/subtract *(ebp+0xfffffffc) 0x00000001/x32"                 "F - test-convert-floating-point-operation/18")
 4343     (check-next-stream-line-equal _test-output-stream "    f3 0f 59/multiply %xmm5 0x00000001/x32"                             "F - test-convert-floating-point-operation/19")
 4344     (check-next-stream-line-equal _test-output-stream "    f3 0f 59/multiply *(ebp+0xfffffffc) 0x00000001/x32"                 "F - test-convert-floating-point-operation/20")
 4345     (check-next-stream-line-equal _test-output-stream "    f3 0f 5e/divide %xmm5 0x00000001/x32"                               "F - test-convert-floating-point-operation/21")
 4346     (check-next-stream-line-equal _test-output-stream "    f3 0f 5e/divide *(ebp+0xfffffffc) 0x00000001/x32"                   "F - test-convert-floating-point-operation/22")
 4347     (check-next-stream-line-equal _test-output-stream "    f3 0f 53/reciprocal %xmm5 0x00000001/x32"                           "F - test-convert-floating-point-operation/23")
 4348     (check-next-stream-line-equal _test-output-stream "    f3 0f 53/reciprocal *(ebp+0xfffffffc) 0x00000001/x32"               "F - test-convert-floating-point-operation/24")
 4349     (check-next-stream-line-equal _test-output-stream "    f3 0f 51/square-root %xmm5 0x00000001/x32"                          "F - test-convert-floating-point-operation/25")
 4350     (check-next-stream-line-equal _test-output-stream "    f3 0f 51/square-root *(ebp+0xfffffffc) 0x00000001/x32"              "F - test-convert-floating-point-operation/26")
 4351     (check-next-stream-line-equal _test-output-stream "    f3 0f 52/inverse-square-root %xmm5 0x00000001/x32"                  "F - test-convert-floating-point-operation/27")
 4352     (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")
 4353     (check-next-stream-line-equal _test-output-stream "    f3 0f 5f/max %xmm5 0x00000001/x32"                                  "F - test-convert-floating-point-operation/29")
 4354     (check-next-stream-line-equal _test-output-stream "    f3 0f 5f/max *(ebp+0xfffffffc) 0x00000001/x32"                      "F - test-convert-floating-point-operation/30")
 4355     (check-next-stream-line-equal _test-output-stream "    f3 0f 5d/min %xmm5 0x00000001/x32"                                  "F - test-convert-floating-point-operation/31")
 4356     (check-next-stream-line-equal _test-output-stream "    f3 0f 5d/min *(ebp+0xfffffffc) 0x00000001/x32"                      "F - test-convert-floating-point-operation/32")
 4357     (check-next-stream-line-equal _test-output-stream "    0f 2f/compare %xmm1 0x00000005/x32"                                 "F - test-convert-floating-point-operation/33")
 4358     (check-next-stream-line-equal _test-output-stream "    0f 2f/compare *(ebp+0xfffffffc) 0x00000001/x32"                     "F - test-convert-floating-point-operation/34")
 4359     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 5/x32"                                             "F - test-convert-floating-point-operation/35")
 4360     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"                                        "F - test-convert-floating-point-operation/36")
 4361     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 1/x32"                                             "F - test-convert-floating-point-operation/37")
 4362     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"                                        "F - test-convert-floating-point-operation/38")
 4363     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"                               "F - test-convert-floating-point-operation/39")
 4364     (check-next-stream-line-equal _test-output-stream "  }"                                                                    "F - test-convert-floating-point-operation/40")
 4365     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"                                                   "F - test-convert-floating-point-operation/41")
 4366     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                                                         "F - test-convert-floating-point-operation/42")
 4367     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                                                 "F - test-convert-floating-point-operation/43")
 4368     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                                                        "F - test-convert-floating-point-operation/44")
 4369     (check-next-stream-line-equal _test-output-stream "  c3/return"                                                            "F - test-convert-floating-point-operation/45")
 4370     # . epilogue
 4371     89/<- %esp 5/r32/ebp
 4372     5d/pop-to-ebp
 4373     c3/return
 4374 
 4375 test-convert-floating-point-dereferenced:
 4376     # . prologue
 4377     55/push-ebp
 4378     89/<- %ebp 4/r32/esp
 4379     # setup
 4380     (clear-stream _test-input-stream)
 4381     (clear-stream $_test-input-buffered-file->buffer)
 4382     (clear-stream _test-output-stream)
 4383     (clear-stream $_test-output-buffered-file->buffer)
 4384     #
 4385     (write _test-input-stream "fn f {\n")
 4386     (write _test-input-stream "  var m: float\n")
 4387     (write _test-input-stream "  var x/xmm1: float <- copy m\n")
 4388     (write _test-input-stream "  var y/eax: (addr float) <- copy 0\n")
 4389     (write _test-input-stream "  x <- multiply *y\n")
 4390     (write _test-input-stream "}\n")
 4391     # convert
 4392     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4393     (flush _test-output-buffered-file)
 4394 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4400     # check output
 4401     (check-next-stream-line-equal _test-output-stream "f:"                                                                     "F - test-convert-floating-point-dereferenced/0")
 4402     (check-next-stream-line-equal _test-output-stream "  # . prologue"                                                         "F - test-convert-floating-point-dereferenced/1")
 4403     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                                                          "F - test-convert-floating-point-dereferenced/2")
 4404     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                                                 "F - test-convert-floating-point-dereferenced/3")
 4405     (check-next-stream-line-equal _test-output-stream "  {"                                                                    "F - test-convert-floating-point-dereferenced/4")
 4406     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"                                                    "F - test-convert-floating-point-dereferenced/5")
 4407     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"                                                    "F - test-convert-floating-point-dereferenced/6")
 4408     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"                                   "F - test-convert-floating-point-dereferenced/7")
 4409     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 1/x32"                                             "F - test-convert-floating-point-dereferenced/8")
 4410     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/copy *(ebp+0xfffffffc) 0x00000001/x32"                     "F - test-convert-floating-point-dereferenced/9")
 4411     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                                               "F - test-convert-floating-point-dereferenced/10")
 4412     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                                             "F - test-convert-floating-point-dereferenced/11")
 4413     (check-next-stream-line-equal _test-output-stream "    f3 0f 59/multiply *eax 0x00000001/x32"                              "F - test-convert-floating-point-dereferenced/12")
 4414     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                                                "F - test-convert-floating-point-dereferenced/13")
 4415     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 1/x32"                                             "F - test-convert-floating-point-dereferenced/14")
 4416     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"                                        "F - test-convert-floating-point-dereferenced/15")
 4417     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"                               "F - test-convert-floating-point-dereferenced/16")
 4418     (check-next-stream-line-equal _test-output-stream "  }"                                                                    "F - test-convert-floating-point-dereferenced/17")
 4419     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"                                                   "F - test-convert-floating-point-dereferenced/18")
 4420     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                                                         "F - test-convert-floating-point-dereferenced/19")
 4421     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                                                 "F - test-convert-floating-point-dereferenced/20")
 4422     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                                                        "F - test-convert-floating-point-dereferenced/21")
 4423     (check-next-stream-line-equal _test-output-stream "  c3/return"                                                            "F - test-convert-floating-point-dereferenced/22")
 4424     # . epilogue
 4425     89/<- %esp 5/r32/ebp
 4426     5d/pop-to-ebp
 4427     c3/return
 4428 
 4429 test-convert-length-of-array:
 4430     # . prologue
 4431     55/push-ebp
 4432     89/<- %ebp 4/r32/esp
 4433     # setup
 4434     (clear-stream _test-input-stream)
 4435     (clear-stream $_test-input-buffered-file->buffer)
 4436     (clear-stream _test-output-stream)
 4437     (clear-stream $_test-output-buffered-file->buffer)
 4438     #
 4439     (write _test-input-stream "fn foo a: (addr array int) {\n")
 4440     (write _test-input-stream "  var b/eax: (addr array int) <- copy a\n")
 4441     (write _test-input-stream "  var c/eax: int <- length b\n")
 4442     (write _test-input-stream "}\n")
 4443     # convert
 4444     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4445     (flush _test-output-buffered-file)
 4446 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4452     # check output
 4453     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array/0")
 4454     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array/1")
 4455     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array/2")
 4456     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array/3")
 4457     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array/4")
 4458     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array/5")
 4459     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array/6")
 4460     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-length-of-array/7")
 4461     (check-next-stream-line-equal _test-output-stream "    8b/-> *eax 0x00000000/r32"  "F - test-convert-length-of-array/8")
 4462     (check-next-stream-line-equal _test-output-stream "    c1/shift 5/subop/>> %eax 0x00000002/imm8"  "F - test-convert-length-of-array/9")
 4463     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array/10")
 4464     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array/11")
 4465     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array/12")
 4466     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array/13")
 4467     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array/14")
 4468     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array/15")
 4469     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array/16")
 4470     # . epilogue
 4471     89/<- %esp 5/r32/ebp
 4472     5d/pop-to-ebp
 4473     c3/return
 4474 
 4475 # special-case for size(byte) when computing array length
 4476 test-convert-length-of-array-of-bytes:
 4477     # . prologue
 4478     55/push-ebp
 4479     89/<- %ebp 4/r32/esp
 4480     # setup
 4481     (clear-stream _test-input-stream)
 4482     (clear-stream $_test-input-buffered-file->buffer)
 4483     (clear-stream _test-output-stream)
 4484     (clear-stream $_test-output-buffered-file->buffer)
 4485     #
 4486     (write _test-input-stream "fn foo a: (addr array byte) {\n")
 4487     (write _test-input-stream "  var b/eax: (addr array byte) <- copy a\n")
 4488     (write _test-input-stream "  var c/eax: int <- length b\n")
 4489     (write _test-input-stream "}\n")
 4490     # convert
 4491     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4492     (flush _test-output-buffered-file)
 4493 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4499     # check output
 4500     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-bytes/0")
 4501     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-bytes/1")
 4502     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-bytes/2")
 4503     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array-of-bytes/3")
 4504     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-bytes/4")
 4505     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-bytes/5")
 4506     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array-of-bytes/6")
 4507     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-length-of-array-of-bytes/7")
 4508     (check-next-stream-line-equal _test-output-stream "    8b/-> *eax 0x00000000/r32"  "F - test-convert-length-of-array-of-bytes/8")
 4509     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array-of-bytes/9")
 4510     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-bytes/10")
 4511     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-bytes/11")
 4512     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-bytes/12")
 4513     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array-of-bytes/13")
 4514     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array-of-bytes/14")
 4515     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-bytes/15")
 4516     # . epilogue
 4517     89/<- %esp 5/r32/ebp
 4518     5d/pop-to-ebp
 4519     c3/return
 4520 
 4521 test-convert-length-of-array-on-stack:
 4522     # . prologue
 4523     55/push-ebp
 4524     89/<- %ebp 4/r32/esp
 4525     # setup
 4526     (clear-stream _test-input-stream)
 4527     (clear-stream $_test-input-buffered-file->buffer)
 4528     (clear-stream _test-output-stream)
 4529     (clear-stream $_test-output-buffered-file->buffer)
 4530     #
 4531     (write _test-input-stream "fn foo {\n")
 4532     (write _test-input-stream "  var a: (array int 3)\n")
 4533     (write _test-input-stream "  var b/eax: int <- length a\n")
 4534     (write _test-input-stream "}\n")
 4535     # convert
 4536     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4537     (flush _test-output-buffered-file)
 4538 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4544     # check output
 4545     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-on-stack/0")
 4546     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-on-stack/1")
 4547     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-on-stack/2")
 4548     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array-on-stack/3")
 4549     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-on-stack/4")
 4550     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-on-stack/5")
 4551     # define x
 4552     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x0000000c)"  "F - test-convert-length-of-array-on-stack/6")
 4553     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"  "F - test-convert-length-of-array-on-stack/7")
 4554     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array-on-stack/8")
 4555     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0xfffffff0) 0x00000000/r32"  "F - test-convert-length-of-array-on-stack/9")
 4556     (check-next-stream-line-equal _test-output-stream "    c1/shift 5/subop/>> %eax 0x00000002/imm8"  "F - test-convert-length-of-array-on-stack/10")
 4557     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array-on-stack/11")
 4558     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000010/imm32"  "F - test-convert-length-of-array-on-stack/12")
 4559     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-on-stack/13")
 4560     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-on-stack/14")
 4561     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-on-stack/15")
 4562     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array-on-stack/16")
 4563     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array-on-stack/17")
 4564     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-on-stack/18")
 4565     # . epilogue
 4566     89/<- %esp 5/r32/ebp
 4567     5d/pop-to-ebp
 4568     c3/return
 4569 
 4570 test-reg-var-def-with-read-of-same-register:
 4571     # . prologue
 4572     55/push-ebp
 4573     89/<- %ebp 4/r32/esp
 4574     # setup
 4575     (clear-stream _test-input-stream)
 4576     (clear-stream $_test-input-buffered-file->buffer)
 4577     (clear-stream _test-output-stream)
 4578     (clear-stream $_test-output-buffered-file->buffer)
 4579     (clear-stream _test-error-stream)
 4580     (clear-stream $_test-error-buffered-file->buffer)
 4581     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)  # bytes of args in call to convert-mu
 4582     68/push 0/imm32
 4583     68/push 0/imm32
 4584     89/<- %edx 4/r32/esp
 4585     (tailor-exit-descriptor %edx 0x10)
 4586     #
 4587     (write _test-input-stream "fn foo {\n")
 4588     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
 4589     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
 4590     (write _test-input-stream "  var x/eax: (addr int) <- index arr, idx\n")
 4591     (write _test-input-stream "}\n")
 4592     # convert
 4593     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 4594     # registers except esp could be clobbered at this point (though they shouldn't be)
 4595     # restore ed
 4596     89/<- %edx 4/r32/esp
 4597     (flush _test-output-buffered-file)
 4598     (flush _test-error-buffered-file)
 4599 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4605 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4611     (check-stream-equal _test-error-stream  ""  "F - test-reg-var-def-with-read-of-same-register: error stream should be empty")
 4612     # check output
 4613     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-reg-var-def-with-read-of-same-register/0")
 4614     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-reg-var-def-with-read-of-same-register/1")
 4615     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-reg-var-def-with-read-of-same-register/2")
 4616     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-reg-var-def-with-read-of-same-register/3")
 4617     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-reg-var-def-with-read-of-same-register/4")
 4618     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-reg-var-def-with-read-of-same-register/5")
 4619     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-reg-var-def-with-read-of-same-register/6")
 4620     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-reg-var-def-with-read-of-same-register/7")
 4621     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-reg-var-def-with-read-of-same-register/8")
 4622     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-reg-var-def-with-read-of-same-register/9")
 4623     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx<<0x00000002 + 4) 0x00000000/r32"  "F - test-reg-var-def-with-read-of-same-register/11")
 4624     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-reg-var-def-with-read-of-same-register/13")
 4625     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-reg-var-def-with-read-of-same-register/14")
 4626     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-reg-var-def-with-read-of-same-register/15")
 4627     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-reg-var-def-with-read-of-same-register/16")
 4628     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-reg-var-def-with-read-of-same-register/17")
 4629     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-reg-var-def-with-read-of-same-register/18")
 4630     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-reg-var-def-with-read-of-same-register/19")
 4631     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-reg-var-def-with-read-of-same-register/20")
 4632     # don't restore from ebp
 4633     81 0/subop/add %esp 8/imm32
 4634     # . epilogue
 4635     5d/pop-to-ebp
 4636     c3/return
 4637 
 4638 test-convert-index-into-array:
 4639     # . prologue
 4640     55/push-ebp
 4641     89/<- %ebp 4/r32/esp
 4642     # setup
 4643     (clear-stream _test-input-stream)
 4644     (clear-stream $_test-input-buffered-file->buffer)
 4645     (clear-stream _test-output-stream)
 4646     (clear-stream $_test-output-buffered-file->buffer)
 4647     #
 4648     (write _test-input-stream "fn foo {\n")
 4649     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
 4650     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
 4651     (write _test-input-stream "  var x/eax: (addr int) <- index arr, idx\n")
 4652     (write _test-input-stream "}\n")
 4653     # convert
 4654     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4655     (flush _test-output-buffered-file)
 4656 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4662     # check output
 4663     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array/0")
 4664     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array/1")
 4665     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array/2")
 4666     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array/3")
 4667     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array/4")
 4668     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array/5")
 4669     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array/6")
 4670     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array/7")
 4671     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array/8")
 4672     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-index-into-array/9")
 4673     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx<<0x00000002 + 4) 0x00000000/r32"  "F - test-convert-index-into-array/10")
 4674     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array/11")
 4675     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array/12")
 4676     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array/13")
 4677     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array/14")
 4678     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array/15")
 4679     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array/16")
 4680     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array/17")
 4681     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array/18")
 4682     # . epilogue
 4683     89/<- %esp 5/r32/ebp
 4684     5d/pop-to-ebp
 4685     c3/return
 4686 
 4687 test-convert-index-into-array-of-bytes:
 4688     # . prologue
 4689     55/push-ebp
 4690     89/<- %ebp 4/r32/esp
 4691     # setup
 4692     (clear-stream _test-input-stream)
 4693     (clear-stream $_test-input-buffered-file->buffer)
 4694     (clear-stream _test-output-stream)
 4695     (clear-stream $_test-output-buffered-file->buffer)
 4696     #
 4697     (write _test-input-stream "fn foo {\n")
 4698     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
 4699     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
 4700     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, idx\n")
 4701     (write _test-input-stream "}\n")
 4702     # convert
 4703     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4704     (flush _test-output-buffered-file)
 4705 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4711     # check output
 4712     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes/0")
 4713     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes/1")
 4714     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes/2")
 4715     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-of-bytes/3")
 4716     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes/4")
 4717     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes/5")
 4718     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-of-bytes/6")
 4719     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array-of-bytes/7")
 4720     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-of-bytes/8")
 4721     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-index-into-array-of-bytes/9")
 4722     (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")
 4723     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-of-bytes/13")
 4724     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes/14")
 4725     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes/15")
 4726     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes/16")
 4727     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes/17")
 4728     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes/18")
 4729     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes/19")
 4730     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes/20")
 4731     # . epilogue
 4732     89/<- %esp 5/r32/ebp
 4733     5d/pop-to-ebp
 4734     c3/return
 4735 
 4736 test-convert-index-into-array-with-literal:
 4737     # . prologue
 4738     55/push-ebp
 4739     89/<- %ebp 4/r32/esp
 4740     # setup
 4741     (clear-stream _test-input-stream)
 4742     (clear-stream $_test-input-buffered-file->buffer)
 4743     (clear-stream _test-output-stream)
 4744     (clear-stream $_test-output-buffered-file->buffer)
 4745     #
 4746     (write _test-input-stream "fn foo {\n")
 4747     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
 4748     (write _test-input-stream "  var x/eax: (addr int) <- index arr, 2\n")
 4749     (write _test-input-stream "}\n")
 4750     # convert
 4751     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4752     (flush _test-output-buffered-file)
 4753 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4759     # check output
 4760     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-with-literal/0")
 4761     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-with-literal/1")
 4762     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-with-literal/2")
 4763     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-with-literal/3")
 4764     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-with-literal/4")
 4765     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-with-literal/5")
 4766     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-with-literal/6")
 4767     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array-with-literal/7")
 4768                                                                                  # 2 * 4 bytes/elem + 4 bytes for size = offset 12
 4769     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + 0x0000000c) 0x00000000/r32"  "F - test-convert-index-into-array-with-literal/8")
 4770     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-with-literal/9")
 4771     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-with-literal/10")
 4772     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-with-literal/11")
 4773     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-with-literal/12")
 4774     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-with-literal/13")
 4775     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-with-literal/14")
 4776     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-with-literal/15")
 4777     # . epilogue
 4778     89/<- %esp 5/r32/ebp
 4779     5d/pop-to-ebp
 4780     c3/return
 4781 
 4782 test-convert-index-into-array-of-bytes-with-literal:
 4783     # . prologue
 4784     55/push-ebp
 4785     89/<- %ebp 4/r32/esp
 4786     # setup
 4787     (clear-stream _test-input-stream)
 4788     (clear-stream $_test-input-buffered-file->buffer)
 4789     (clear-stream _test-output-stream)
 4790     (clear-stream $_test-output-buffered-file->buffer)
 4791     #
 4792     (write _test-input-stream "fn foo {\n")
 4793     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
 4794     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, 2\n")
 4795     (write _test-input-stream "}\n")
 4796     # convert
 4797     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4798     (flush _test-output-buffered-file)
 4799 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4805     # check output
 4806     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-with-literal/0")
 4807     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-with-literal/1")
 4808     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-with-literal/2")
 4809     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-of-bytes-with-literal/3")
 4810     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-with-literal/4")
 4811     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-with-literal/5")
 4812     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-of-bytes-with-literal/6")
 4813     (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")
 4814                                                                                  # 2 * 1 byte/elem + 4 bytes for size = offset 6
 4815     (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")
 4816     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes-with-literal/9")
 4817     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-with-literal/10")
 4818     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-with-literal/11")
 4819     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-with-literal/12")
 4820     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes-with-literal/13")
 4821     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes-with-literal/14")
 4822     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-with-literal/15")
 4823     # . epilogue
 4824     89/<- %esp 5/r32/ebp
 4825     5d/pop-to-ebp
 4826     c3/return
 4827 
 4828 test-convert-index-into-array-on-stack:
 4829     # . prologue
 4830     55/push-ebp
 4831     89/<- %ebp 4/r32/esp
 4832     # setup
 4833     (clear-stream _test-input-stream)
 4834     (clear-stream $_test-input-buffered-file->buffer)
 4835     (clear-stream _test-output-stream)
 4836     (clear-stream $_test-output-buffered-file->buffer)
 4837     #
 4838     (write _test-input-stream "fn foo {\n")
 4839     (write _test-input-stream "  var arr: (array int 3)\n")
 4840     (write _test-input-stream "  var idx/eax: int <- copy 2\n")
 4841     (write _test-input-stream "  var x/eax: (addr int) <- index arr, idx\n")
 4842     (write _test-input-stream "}\n")
 4843     # convert
 4844     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4845     (flush _test-output-buffered-file)
 4846 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4852     # check output
 4853     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-on-stack/0")
 4854     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-on-stack/1")
 4855     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-on-stack/2")
 4856     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-on-stack/3")
 4857     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-on-stack/4")
 4858     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-on-stack/5")
 4859     # var arr
 4860     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x0000000c)"          "F - test-convert-index-into-array-on-stack/6")
 4861     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"                "F - test-convert-index-into-array-on-stack/7")
 4862     # var idx
 4863     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-on-stack/8")
 4864     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 2/imm32"                  "F - test-convert-index-into-array-on-stack/9")
 4865     # var x is at (ebp-0x10) + idx<<2 + 4 = ebp + idx<<2 - 0xc
 4866     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp + eax<<0x00000002 + 0xfffffff4) 0x00000000/r32"  "F - test-convert-index-into-array-on-stack/10")
 4867     # reclaim idx
 4868     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-on-stack/11")
 4869     # reclaim arr
 4870     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000010/imm32"    "F - test-convert-index-into-array-on-stack/12")
 4871     #
 4872     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-on-stack/13")
 4873     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-on-stack/14")
 4874     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-on-stack/15")
 4875     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-on-stack/16")
 4876     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-on-stack/17")
 4877     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-on-stack/18")
 4878     # . epilogue
 4879     89/<- %esp 5/r32/ebp
 4880     5d/pop-to-ebp
 4881     c3/return
 4882 
 4883 test-convert-index-into-array-on-stack-with-literal:
 4884     # . prologue
 4885     55/push-ebp
 4886     89/<- %ebp 4/r32/esp
 4887     # setup
 4888     (clear-stream _test-input-stream)
 4889     (clear-stream $_test-input-buffered-file->buffer)
 4890     (clear-stream _test-output-stream)
 4891     (clear-stream $_test-output-buffered-file->buffer)
 4892     #
 4893     (write _test-input-stream "fn foo {\n")
 4894     (write _test-input-stream "  var arr: (array int 3)\n")
 4895     (write _test-input-stream "  var x/eax: (addr int) <- index arr, 2\n")
 4896     (write _test-input-stream "}\n")
 4897     # convert
 4898     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4899     (flush _test-output-buffered-file)
 4900 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4906     # check output
 4907     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-on-stack-with-literal/0")
 4908     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-on-stack-with-literal/1")
 4909     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-on-stack-with-literal/2")
 4910     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-on-stack-with-literal/3")
 4911     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-on-stack-with-literal/4")
 4912     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-on-stack-with-literal/5")
 4913     # var arr
 4914     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x0000000c)"          "F - test-convert-index-into-array-on-stack-with-literal/6")
 4915     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"                "F - test-convert-index-into-array-on-stack-with-literal/7")
 4916     # var x
 4917     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-on-stack-with-literal/8")
 4918     # x is at (ebp-0x10) + 4 + 2*4 = ebp-4
 4919     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp + 0xfffffffc) 0x00000000/r32"  "F - test-convert-index-into-array-on-stack-with-literal/9")
 4920     # reclaim x
 4921     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-on-stack-with-literal/10")
 4922     # reclaim arr
 4923     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000010/imm32"    "F - test-convert-index-into-array-on-stack-with-literal/11")
 4924     #
 4925     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-on-stack-with-literal/12")
 4926     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-on-stack-with-literal/13")
 4927     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-on-stack-with-literal/14")
 4928     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-on-stack-with-literal/15")
 4929     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-on-stack-with-literal/16")
 4930     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-on-stack-with-literal/17")
 4931     # . epilogue
 4932     89/<- %esp 5/r32/ebp
 4933     5d/pop-to-ebp
 4934     c3/return
 4935 
 4936 test-convert-index-into-array-of-bytes-on-stack-with-literal:
 4937     # . prologue
 4938     55/push-ebp
 4939     89/<- %ebp 4/r32/esp
 4940     # setup
 4941     (clear-stream _test-input-stream)
 4942     (clear-stream $_test-input-buffered-file->buffer)
 4943     (clear-stream _test-output-stream)
 4944     (clear-stream $_test-output-buffered-file->buffer)
 4945     #
 4946     (write _test-input-stream "fn foo {\n")
 4947     (write _test-input-stream "  var arr: (array byte 3)\n")
 4948     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, 2\n")
 4949     (write _test-input-stream "}\n")
 4950     # convert
 4951     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4952     (flush _test-output-buffered-file)
 4953 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4959     # check output
 4960     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/0")
 4961     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/1")
 4962     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/2")
 4963     (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")
 4964     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/4")
 4965     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/5")
 4966     # var arr
 4967     (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")
 4968     (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")
 4969     # var x
 4970     (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")
 4971     # x is at (ebp-7) + 4 + 2 = ebp-1
 4972     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp + 0xffffffff) 0x00000000/r32"  "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/9")
 4973     # reclaim x
 4974     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/10")
 4975     # reclaim arr
 4976     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000007/imm32"    "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/11")
 4977     #
 4978     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/12")
 4979     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/13")
 4980     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/14")
 4981     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/15")
 4982     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/16")
 4983     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/17")
 4984     # . epilogue
 4985     89/<- %esp 5/r32/ebp
 4986     5d/pop-to-ebp
 4987     c3/return
 4988 
 4989 test-convert-index-into-array-using-offset:
 4990     # . prologue
 4991     55/push-ebp
 4992     89/<- %ebp 4/r32/esp
 4993     # setup
 4994     (clear-stream _test-input-stream)
 4995     (clear-stream $_test-input-buffered-file->buffer)
 4996     (clear-stream _test-output-stream)
 4997     (clear-stream $_test-output-buffered-file->buffer)
 4998     #
 4999     (write _test-input-stream "fn foo {\n")
 5000     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
 5001     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
 5002     (write _test-input-stream "  var off/ecx: (offset int) <- compute-offset arr, idx\n")
 5003     (write _test-input-stream "  var x/eax: (addr int) <- index arr, off\n")
 5004     (write _test-input-stream "}\n")
 5005     # convert
 5006     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5007     (flush _test-output-buffered-file)
 5008 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5014     # check output
 5015     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-using-offset/0")
 5016     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-using-offset/1")
 5017     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-using-offset/2")
 5018     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-using-offset/3")
 5019     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-using-offset/4")
 5020     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-using-offset/5")
 5021     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-using-offset/6")
 5022     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array-using-offset/7")
 5023     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-using-offset/8")
 5024     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-index-into-array-using-offset/9")
 5025     (check-next-stream-line-equal _test-output-stream "    69/multiply %ecx 0x00000004/imm32 0x00000001/r32"  "F - test-convert-index-into-array-using-offset/10")
 5026     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx + 4) 0x00000000/r32"  "F - test-convert-index-into-array-using-offset/11")
 5027     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-using-offset/12")
 5028     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-using-offset/13")
 5029     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-using-offset/14")
 5030     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-using-offset/15")
 5031     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-using-offset/16")
 5032     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-using-offset/17")
 5033     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-using-offset/18")
 5034     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-using-offset/19")
 5035     # . epilogue
 5036     89/<- %esp 5/r32/ebp
 5037     5d/pop-to-ebp
 5038     c3/return
 5039 
 5040 test-convert-index-into-array-of-bytes-using-offset:
 5041     # . prologue
 5042     55/push-ebp
 5043     89/<- %ebp 4/r32/esp
 5044     # setup
 5045     (clear-stream _test-input-stream)
 5046     (clear-stream $_test-input-buffered-file->buffer)
 5047     (clear-stream _test-output-stream)
 5048     (clear-stream $_test-output-buffered-file->buffer)
 5049     #
 5050     (write _test-input-stream "fn foo {\n")
 5051     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
 5052     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
 5053     (write _test-input-stream "  var off/ecx: (offset byte) <- compute-offset arr, idx\n")
 5054     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, off\n")
 5055     (write _test-input-stream "}\n")
 5056     # convert
 5057     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5058     (flush _test-output-buffered-file)
 5059 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5065     # check output
 5066     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-using-offset/0")
 5067     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-using-offset/1")
 5068     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-using-offset/2")
 5069     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-of-bytes-using-offset/3")
 5070     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-using-offset/4")
 5071     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-using-offset/5")
 5072     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-of-bytes-using-offset/6")
 5073     (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")
 5074     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-of-bytes-using-offset/8")
 5075     (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")
 5076     (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")
 5077     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx + 4) 0x00000000/r32"  "F - test-convert-index-into-array-of-bytes-using-offset/11")
 5078     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-of-bytes-using-offset/12")
 5079     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes-using-offset/13")
 5080     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-using-offset/14")
 5081     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-using-offset/15")
 5082     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-using-offset/16")
 5083     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes-using-offset/17")
 5084     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes-using-offset/18")
 5085     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-using-offset/19")
 5086     # . epilogue
 5087     89/<- %esp 5/r32/ebp
 5088     5d/pop-to-ebp
 5089     c3/return
 5090 
 5091 test-convert-index-into-array-using-offset-on-stack:
 5092     # . prologue
 5093     55/push-ebp
 5094     89/<- %ebp 4/r32/esp
 5095     # setup
 5096     (clear-stream _test-input-stream)
 5097     (clear-stream $_test-input-buffered-file->buffer)
 5098     (clear-stream _test-output-stream)
 5099     (clear-stream $_test-output-buffered-file->buffer)
 5100     #
 5101     (write _test-input-stream "fn foo {\n")
 5102     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
 5103     (write _test-input-stream "  var idx: int\n")
 5104     (write _test-input-stream "  var off/ecx: (offset int) <- compute-offset arr, idx\n")
 5105     (write _test-input-stream "  var x/eax: (addr int) <- index arr, off\n")
 5106     (write _test-input-stream "}\n")
 5107     # convert
 5108     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5109     (flush _test-output-buffered-file)
 5110 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5116     # check output
 5117     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-using-offset-on-stack/0")
 5118     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-using-offset-on-stack/1")
 5119     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-using-offset-on-stack/2")
 5120     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-using-offset-on-stack/3")
 5121     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-using-offset-on-stack/4")
 5122     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-using-offset-on-stack/5")
 5123     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-using-offset-on-stack/6")
 5124     (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")
 5125     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"                         "F - test-convert-index-into-array-using-offset-on-stack/8")
 5126     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-using-offset-on-stack/9")
 5127     (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")
 5128     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx + 4) 0x00000000/r32"  "F - test-convert-index-into-array-using-offset-on-stack/11")
 5129     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-using-offset-on-stack/12")
 5130     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"    "F - test-convert-index-into-array-using-offset-on-stack/13")
 5131     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-using-offset-on-stack/14")
 5132     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-using-offset-on-stack/15")
 5133     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-using-offset-on-stack/16")
 5134     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-using-offset-on-stack/17")
 5135     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-using-offset-on-stack/18")
 5136     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-using-offset-on-stack/19")
 5137     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-using-offset-on-stack/20")
 5138     # . epilogue
 5139     89/<- %esp 5/r32/ebp
 5140     5d/pop-to-ebp
 5141     c3/return
 5142 
 5143 test-convert-index-into-array-of-bytes-using-offset-on-stack:
 5144     # . prologue
 5145     55/push-ebp
 5146     89/<- %ebp 4/r32/esp
 5147     # setup
 5148     (clear-stream _test-input-stream)
 5149     (clear-stream $_test-input-buffered-file->buffer)
 5150     (clear-stream _test-output-stream)
 5151     (clear-stream $_test-output-buffered-file->buffer)
 5152     #
 5153     (write _test-input-stream "fn foo {\n")
 5154     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
 5155     (write _test-input-stream "  var idx: int\n")
 5156     (write _test-input-stream "  var off/ecx: (offset byte) <- compute-offset arr, idx\n")
 5157     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, off\n")
 5158     (write _test-input-stream "}\n")
 5159     # convert
 5160     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5161     (flush _test-output-buffered-file)
 5162 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5168     # check output
 5169     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/0")
 5170     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/1")
 5171     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/2")
 5172     (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")
 5173     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/4")
 5174     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/5")
 5175     (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")
 5176     (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")
 5177     (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")
 5178     (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")
 5179     (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")
 5180     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx + 4) 0x00000000/r32"  "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/11")
 5181     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/12")
 5182     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"    "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/13")
 5183     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/14")
 5184     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/15")
 5185     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/16")
 5186     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/17")
 5187     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/18")
 5188     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/19")
 5189     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/20")
 5190     # . epilogue
 5191     89/<- %esp 5/r32/ebp
 5192     5d/pop-to-ebp
 5193     c3/return
 5194 
 5195 test-convert-function-and-type-definition:
 5196     # . prologue
 5197     55/push-ebp
 5198     89/<- %ebp 4/r32/esp
 5199     # setup
 5200     (clear-stream _test-input-stream)
 5201     (clear-stream $_test-input-buffered-file->buffer)
 5202     (clear-stream _test-output-stream)
 5203     (clear-stream $_test-output-buffered-file->buffer)
 5204     #
 5205     (write _test-input-stream "fn foo a: (addr t) {\n")
 5206     (write _test-input-stream "  var _a/eax: (addr t) <- copy a\n")
 5207     (write _test-input-stream "  var b/ecx: (addr int) <- get _a, x\n")
 5208     (write _test-input-stream "  var c/ecx: (addr int) <- get _a, y\n")
 5209     (write _test-input-stream "}\n")
 5210     (write _test-input-stream "type t {\n")
 5211     (write _test-input-stream "  x: int\n")
 5212     (write _test-input-stream "  y: int\n")
 5213     (write _test-input-stream "}\n")
 5214     # convert
 5215     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5216     (flush _test-output-buffered-file)
 5217 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5223     # check output
 5224     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-and-type-definition/0")
 5225     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-and-type-definition/1")
 5226     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-and-type-definition/2")
 5227     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-and-type-definition/3")
 5228     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-and-type-definition/4")
 5229     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-and-type-definition/5")
 5230     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-and-type-definition/6")
 5231     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-function-and-type-definition/7")
 5232     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-and-type-definition/8")
 5233     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + 0x00000000) 0x00000001/r32"  "F - test-convert-function-and-type-definition/9")
 5234     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + 0x00000004) 0x00000001/r32"  "F - test-convert-function-and-type-definition/11")
 5235     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-and-type-definition/13")
 5236     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-function-and-type-definition/14")
 5237     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-and-type-definition/15")
 5238     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-and-type-definition/16")
 5239     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-and-type-definition/17")
 5240     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-and-type-definition/18")
 5241     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-and-type-definition/19")
 5242     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-and-type-definition/20")
 5243     # . epilogue
 5244     89/<- %esp 5/r32/ebp
 5245     5d/pop-to-ebp
 5246     c3/return
 5247 
 5248 test-type-definition-with-array:
 5249     # . prologue
 5250     55/push-ebp
 5251     89/<- %ebp 4/r32/esp
 5252     # setup
 5253     (clear-stream _test-input-stream)
 5254     (clear-stream $_test-input-buffered-file->buffer)
 5255     (clear-stream _test-output-stream)
 5256     (clear-stream $_test-output-buffered-file->buffer)
 5257     (clear-stream _test-error-stream)
 5258     (clear-stream $_test-error-buffered-file->buffer)
 5259     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 5260     68/push 0/imm32
 5261     68/push 0/imm32
 5262     89/<- %edx 4/r32/esp
 5263     (tailor-exit-descriptor %edx 0x10)
 5264     #
 5265     (write _test-input-stream "type t {\n")
 5266     (write _test-input-stream "  a: (array int 3)\n")
 5267     (write _test-input-stream "}\n")
 5268     # convert
 5269     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 5270     # registers except esp clobbered at this point
 5271     # restore ed
 5272     89/<- %edx 4/r32/esp
 5273     (flush _test-output-buffered-file)
 5274     (flush _test-error-buffered-file)
 5275 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5281     # check output
 5282     (check-stream-equal _test-output-stream  ""  "F - test-type-definition-with-array: output should be empty")
 5283     (check-next-stream-line-equal _test-error-stream  "type t: 'array' elements not allowed for now"  "F - test-type-definition-with-array: error message")
 5284     # check that stop(1) was called
 5285     (check-ints-equal *(edx+4) 2 "F - test-type-definition-with-array: exit status")
 5286     # don't restore from ebp
 5287     81 0/subop/add %esp 8/imm32
 5288     # . epilogue
 5289     5d/pop-to-ebp
 5290     c3/return
 5291 
 5292 test-type-definition-with-addr:
 5293     # . prologue
 5294     55/push-ebp
 5295     89/<- %ebp 4/r32/esp
 5296     # setup
 5297     (clear-stream _test-input-stream)
 5298     (clear-stream $_test-input-buffered-file->buffer)
 5299     (clear-stream _test-output-stream)
 5300     (clear-stream $_test-output-buffered-file->buffer)
 5301     (clear-stream _test-error-stream)
 5302     (clear-stream $_test-error-buffered-file->buffer)
 5303     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 5304     68/push 0/imm32
 5305     68/push 0/imm32
 5306     89/<- %edx 4/r32/esp
 5307     (tailor-exit-descriptor %edx 0x10)
 5308     #
 5309     (write _test-input-stream "type t {\n")
 5310     (write _test-input-stream "  a: (addr int)\n")
 5311     (write _test-input-stream "}\n")
 5312     # convert
 5313     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 5314     # registers except esp clobbered at this point
 5315     # restore ed
 5316     89/<- %edx 4/r32/esp
 5317     (flush _test-output-buffered-file)
 5318     (flush _test-error-buffered-file)
 5319 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5325     # check output
 5326     (check-stream-equal _test-output-stream  ""  "F - test-type-definition-with-addr: output should be empty")
 5327     (check-next-stream-line-equal _test-error-stream  "type t: 'addr' elements not allowed"  "F - test-type-definition-with-addr: error message")
 5328     # check that stop(1) was called
 5329     (check-ints-equal *(edx+4) 2 "F - test-type-definition-with-addr: exit status")
 5330     # don't restore from ebp
 5331     81 0/subop/add %esp 8/imm32
 5332     # . epilogue
 5333     5d/pop-to-ebp
 5334     c3/return
 5335 
 5336 test-convert-function-with-local-var-with-user-defined-type:
 5337     # . prologue
 5338     55/push-ebp
 5339     89/<- %ebp 4/r32/esp
 5340     # setup
 5341     (clear-stream _test-input-stream)
 5342     (clear-stream $_test-input-buffered-file->buffer)
 5343     (clear-stream _test-output-stream)
 5344     (clear-stream $_test-output-buffered-file->buffer)
 5345     #
 5346     (write _test-input-stream "fn foo {\n")
 5347     (write _test-input-stream "  var a: t\n")
 5348     (write _test-input-stream "}\n")
 5349     (write _test-input-stream "type t {\n")
 5350     (write _test-input-stream "  x: int\n")
 5351     (write _test-input-stream "  y: int\n")
 5352     (write _test-input-stream "}\n")
 5353     # convert
 5354     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5355     (flush _test-output-buffered-file)
 5356 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5362     # check output
 5363     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-with-user-defined-type/0")
 5364     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-with-user-defined-type/1")
 5365     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-with-user-defined-type/2")
 5366     (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")
 5367     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-with-user-defined-type/4")
 5368     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-with-user-defined-type/5")
 5369     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-with-user-defined-type/6")
 5370     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-with-user-defined-type/7")
 5371     (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")
 5372     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-with-user-defined-type/9")
 5373     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-with-user-defined-type/10")
 5374     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-with-user-defined-type/11")
 5375     (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")
 5376     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-with-user-defined-type/13")
 5377     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-with-user-defined-type/14")
 5378     # . epilogue
 5379     89/<- %esp 5/r32/ebp
 5380     5d/pop-to-ebp
 5381     c3/return
 5382 
 5383 test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type:
 5384     # . prologue
 5385     55/push-ebp
 5386     89/<- %ebp 4/r32/esp
 5387     # setup
 5388     (clear-stream _test-input-stream)
 5389     (clear-stream $_test-input-buffered-file->buffer)
 5390     (clear-stream _test-output-stream)
 5391     (clear-stream $_test-output-buffered-file->buffer)
 5392     #
 5393     (write _test-input-stream "fn foo {\n")
 5394     (write _test-input-stream "  var a: t\n")
 5395     (write _test-input-stream "}\n")
 5396     (write _test-input-stream "type t {\n")
 5397     (write _test-input-stream "  x: s\n")
 5398     (write _test-input-stream "}\n")
 5399     (write _test-input-stream "type s {\n")
 5400     (write _test-input-stream "  z: int\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-local-var-with-user-defined-type-containing-user-defined-type/0")
 5413     (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")
 5414     (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")
 5415     (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")
 5416     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/4")
 5417     (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")
 5418     (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")
 5419     (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")
 5420     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/9")
 5421     (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")
 5422     (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")
 5423     (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")
 5424     (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")
 5425     (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")
 5426     # . epilogue
 5427     89/<- %esp 5/r32/ebp
 5428     5d/pop-to-ebp
 5429     c3/return
 5430 
 5431 test-convert-function-call-with-arg-of-user-defined-type:
 5432     # . prologue
 5433     55/push-ebp
 5434     89/<- %ebp 4/r32/esp
 5435     # setup
 5436     (clear-stream _test-input-stream)
 5437     (clear-stream $_test-input-buffered-file->buffer)
 5438     (clear-stream _test-output-stream)
 5439     (clear-stream $_test-output-buffered-file->buffer)
 5440     #
 5441     (write _test-input-stream "fn f {\n")
 5442     (write _test-input-stream "  var a: t\n")
 5443     (write _test-input-stream "  foo a\n")
 5444     (write _test-input-stream "}\n")
 5445     (write _test-input-stream "fn foo x: t {\n")
 5446     (write _test-input-stream "}\n")
 5447     (write _test-input-stream "type t {\n")
 5448     (write _test-input-stream "  x: int\n")
 5449     (write _test-input-stream "  y: int\n")
 5450     (write _test-input-stream "}\n")
 5451     # convert
 5452     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5453     (flush _test-output-buffered-file)
 5454 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5460     # check output
 5461     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-arg-of-user-defined-type/0")
 5462     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/1")
 5463     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/2")
 5464     (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")
 5465     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type/4")
 5466     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"     "F - test-convert-function-call-with-arg-of-user-defined-type/5")
 5467     # var a: t
 5468     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-call-with-arg-of-user-defined-type/6")
 5469     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-call-with-arg-of-user-defined-type/7")
 5470     # foo a
 5471     (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")
 5472     #
 5473     (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")
 5474     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type/10")
 5475     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"    "F - test-convert-function-call-with-arg-of-user-defined-type/11")
 5476     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/12")
 5477     (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")
 5478     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/14")
 5479     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/15")
 5480     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call-with-arg-of-user-defined-type/16")
 5481     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/17")
 5482     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/18")
 5483     (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")
 5484     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/20")
 5485     (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")
 5486     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/22")
 5487     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/23")
 5488     # . epilogue
 5489     89/<- %esp 5/r32/ebp
 5490     5d/pop-to-ebp
 5491     c3/return
 5492 
 5493 test-convert-function-call-with-arg-of-user-defined-type-register-indirect:
 5494     # . prologue
 5495     55/push-ebp
 5496     89/<- %ebp 4/r32/esp
 5497     # setup
 5498     (clear-stream _test-input-stream)
 5499     (clear-stream $_test-input-buffered-file->buffer)
 5500     (clear-stream _test-output-stream)
 5501     (clear-stream $_test-output-buffered-file->buffer)
 5502     #
 5503     (write _test-input-stream "fn f {\n")
 5504     (write _test-input-stream "  var a/eax: (addr t) <- copy 0\n")
 5505     (write _test-input-stream "  foo *a\n")
 5506     (write _test-input-stream "}\n")
 5507     (write _test-input-stream "fn foo x: t {\n")
 5508     (write _test-input-stream "}\n")
 5509     (write _test-input-stream "type t {\n")
 5510     (write _test-input-stream "  x: int\n")
 5511     (write _test-input-stream "  y: int\n")
 5512     (write _test-input-stream "}\n")
 5513     # convert
 5514     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5515     (flush _test-output-buffered-file)
 5516 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5522     # check output
 5523     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-arg-of-user-defined-type/0")
 5524     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/1")
 5525     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/2")
 5526     (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")
 5527     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type/4")
 5528     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"     "F - test-convert-function-call-with-arg-of-user-defined-type/5")
 5529     # var a
 5530     (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")
 5531     (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")
 5532     # foo a
 5533     (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")
 5534     #
 5535     (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")
 5536     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type/10")
 5537     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"    "F - test-convert-function-call-with-arg-of-user-defined-type/11")
 5538     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/12")
 5539     (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")
 5540     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/14")
 5541     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/15")
 5542     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call-with-arg-of-user-defined-type/16")
 5543     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/17")
 5544     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/18")
 5545     (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")
 5546     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/20")
 5547     (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")
 5548     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/22")
 5549     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/23")
 5550     # . epilogue
 5551     89/<- %esp 5/r32/ebp
 5552     5d/pop-to-ebp
 5553     c3/return
 5554 
 5555 # we don't have special support for call-by-reference; just explicitly create
 5556 # a new variable with the address of the arg
 5557 test-convert-function-call-with-arg-of-user-defined-type-by-reference:
 5558     # . prologue
 5559     55/push-ebp
 5560     89/<- %ebp 4/r32/esp
 5561     # setup
 5562     (clear-stream _test-input-stream)
 5563     (clear-stream $_test-input-buffered-file->buffer)
 5564     (clear-stream _test-output-stream)
 5565     (clear-stream $_test-output-buffered-file->buffer)
 5566     #
 5567     (write _test-input-stream "fn f {\n")
 5568     (write _test-input-stream "  var a: t\n")
 5569     (write _test-input-stream "  var b/eax: (addr t) <- address a\n")
 5570     (write _test-input-stream "  foo b\n")
 5571     (write _test-input-stream "}\n")
 5572     (write _test-input-stream "fn foo x: (addr t) {\n")
 5573     (write _test-input-stream "  var x/ecx: (addr int) <- copy x\n")
 5574     (write _test-input-stream "  increment *x\n")
 5575     (write _test-input-stream "}\n")
 5576     (write _test-input-stream "type t {\n")
 5577     (write _test-input-stream "  x: int\n")
 5578     (write _test-input-stream "  y: int\n")
 5579     (write _test-input-stream "}\n")
 5580     # convert
 5581     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5582     (flush _test-output-buffered-file)
 5583 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5589     # check output
 5590     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/0")
 5591     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/1")
 5592     (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")
 5593     (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")
 5594     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/4")
 5595     (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")
 5596     # var a: t
 5597     (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")
 5598     (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")
 5599     # var b/eax: (addr t)
 5600     (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")
 5601     (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")
 5602     # foo a
 5603     (check-next-stream-line-equal _test-output-stream "    (foo %eax)"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/10")
 5604     #
 5605     (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")
 5606     (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")
 5607     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/13")
 5608     (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")
 5609     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/15")
 5610     (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")
 5611     (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")
 5612     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/18")
 5613     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/19")
 5614     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/20")
 5615     (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")
 5616     (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")
 5617     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/23")
 5618     (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")
 5619     (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")
 5620     (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")
 5621     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *ecx"  "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/27")
 5622     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/28")
 5623     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/29")
 5624     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/30")
 5625     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/31")
 5626     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/32")
 5627     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/33")
 5628     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/34")
 5629     # . epilogue
 5630     89/<- %esp 5/r32/ebp
 5631     5d/pop-to-ebp
 5632     c3/return
 5633 
 5634 test-convert-get-on-local-variable:
 5635     # . prologue
 5636     55/push-ebp
 5637     89/<- %ebp 4/r32/esp
 5638     # setup
 5639     (clear-stream _test-input-stream)
 5640     (clear-stream $_test-input-buffered-file->buffer)
 5641     (clear-stream _test-output-stream)
 5642     (clear-stream $_test-output-buffered-file->buffer)
 5643     #
 5644     (write _test-input-stream "fn foo {\n")
 5645     (write _test-input-stream "  var a: t\n")
 5646     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 5647     (write _test-input-stream "}\n")
 5648     (write _test-input-stream "type t {\n")
 5649     (write _test-input-stream "  x: int\n")
 5650     (write _test-input-stream "  y: int\n")
 5651     (write _test-input-stream "}\n")
 5652     # convert
 5653     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5654     (flush _test-output-buffered-file)
 5655 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5661     # check output
 5662     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-get-on-local-variable/0")
 5663     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-get-on-local-variable/1")
 5664     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-get-on-local-variable/2")
 5665     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-get-on-local-variable/3")
 5666     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-get-on-local-variable/4")
 5667     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-get-on-local-variable/5")
 5668     # var a
 5669     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-get-on-local-variable/6")
 5670     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-get-on-local-variable/7")
 5671     # var c
 5672     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-get-on-local-variable/8")
 5673     # get
 5674     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp+0xfffffffc) 0x00000001/r32"  "F - test-convert-get-on-local-variable/9")
 5675     # reclaim c
 5676     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-get-on-local-variable/10")
 5677     # reclaim a
 5678     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000008/imm32"  "F - test-convert-get-on-local-variable/11")
 5679     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-get-on-local-variable/12")
 5680     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-get-on-local-variable/13")
 5681     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-get-on-local-variable/14")
 5682     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-get-on-local-variable/15")
 5683     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-get-on-local-variable/16")
 5684     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-get-on-local-variable/17")
 5685     # . epilogue
 5686     89/<- %esp 5/r32/ebp
 5687     5d/pop-to-ebp
 5688     c3/return
 5689 
 5690 test-convert-get-on-function-argument:
 5691     # . prologue
 5692     55/push-ebp
 5693     89/<- %ebp 4/r32/esp
 5694     # setup
 5695     (clear-stream _test-input-stream)
 5696     (clear-stream $_test-input-buffered-file->buffer)
 5697     (clear-stream _test-output-stream)
 5698     (clear-stream $_test-output-buffered-file->buffer)
 5699     #
 5700     (write _test-input-stream "fn foo a: t {\n")
 5701     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 5702     (write _test-input-stream "}\n")
 5703     (write _test-input-stream "type t {\n")
 5704     (write _test-input-stream "  x: int\n")
 5705     (write _test-input-stream "  y: int\n")
 5706     (write _test-input-stream "}\n")
 5707     # convert
 5708     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5709     (flush _test-output-buffered-file)
 5710 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5716     # check output
 5717     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-get-on-function-argument/0")
 5718     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-get-on-function-argument/1")
 5719     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-get-on-function-argument/2")
 5720     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-get-on-function-argument/3")
 5721     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-get-on-function-argument/4")
 5722     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-get-on-function-argument/5")
 5723     # var c
 5724     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-get-on-function-argument/6")
 5725     # get
 5726     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp+0x0000000c) 0x00000001/r32"  "F - test-convert-get-on-function-argument/7")
 5727     # reclaim c
 5728     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-get-on-function-argument/8")
 5729     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-get-on-function-argument/9")
 5730     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-get-on-function-argument/10")
 5731     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-get-on-function-argument/11")
 5732     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-get-on-function-argument/12")
 5733     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-get-on-function-argument/13")
 5734     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-get-on-function-argument/14")
 5735     # . epilogue
 5736     89/<- %esp 5/r32/ebp
 5737     5d/pop-to-ebp
 5738     c3/return
 5739 
 5740 test-convert-get-on-function-argument-with-known-type:
 5741     # . prologue
 5742     55/push-ebp
 5743     89/<- %ebp 4/r32/esp
 5744     # setup
 5745     (clear-stream _test-input-stream)
 5746     (clear-stream $_test-input-buffered-file->buffer)
 5747     (clear-stream _test-output-stream)
 5748     (clear-stream $_test-output-buffered-file->buffer)
 5749     #
 5750     (write _test-input-stream "type t {\n")
 5751     (write _test-input-stream "  x: int\n")
 5752     (write _test-input-stream "  y: int\n")
 5753     (write _test-input-stream "}\n")
 5754     (write _test-input-stream "fn foo a: t {\n")
 5755     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 5756     (write _test-input-stream "}\n")
 5757     # convert
 5758     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5759     (flush _test-output-buffered-file)
 5760 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5766     # check output
 5767     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-get-on-function-argument-with-known-type/0")
 5768     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-get-on-function-argument-with-known-type/1")
 5769     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-get-on-function-argument-with-known-type/2")
 5770     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-get-on-function-argument-with-known-type/3")
 5771     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-get-on-function-argument-with-known-type/4")
 5772     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-get-on-function-argument-with-known-type/5")
 5773     # var c
 5774     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-get-on-function-argument-with-known-type/6")
 5775     # get
 5776     (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")
 5777     # reclaim c
 5778     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-get-on-function-argument-with-known-type/8")
 5779     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-get-on-function-argument-with-known-type/9")
 5780     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-get-on-function-argument-with-known-type/10")
 5781     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-get-on-function-argument-with-known-type/11")
 5782     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-get-on-function-argument-with-known-type/12")
 5783     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-get-on-function-argument-with-known-type/13")
 5784     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-get-on-function-argument-with-known-type/14")
 5785     # . epilogue
 5786     89/<- %esp 5/r32/ebp
 5787     5d/pop-to-ebp
 5788     c3/return
 5789 
 5790 test-add-with-too-many-inouts:
 5791     # . prologue
 5792     55/push-ebp
 5793     89/<- %ebp 4/r32/esp
 5794     # setup
 5795     (clear-stream _test-input-stream)
 5796     (clear-stream $_test-input-buffered-file->buffer)
 5797     (clear-stream _test-output-stream)
 5798     (clear-stream $_test-output-buffered-file->buffer)
 5799     (clear-stream _test-error-stream)
 5800     (clear-stream $_test-error-buffered-file->buffer)
 5801     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 5802     68/push 0/imm32
 5803     68/push 0/imm32
 5804     89/<- %edx 4/r32/esp
 5805     (tailor-exit-descriptor %edx 0x10)
 5806     #
 5807     (write _test-input-stream "fn foo {\n")
 5808     (write _test-input-stream "  var a: int\n")
 5809     (write _test-input-stream "  var b/ecx: int <- add a, 0\n")
 5810     (write _test-input-stream "}\n")
 5811     # convert
 5812     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 5813     # registers except esp clobbered at this point
 5814     # restore ed
 5815     89/<- %edx 4/r32/esp
 5816     (flush _test-output-buffered-file)
 5817     (flush _test-error-buffered-file)
 5818 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5824     # check output
 5825     (check-stream-equal _test-output-stream  ""  "F - test-add-with-too-many-inouts: output should be empty")
 5826     (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")
 5827     # check that stop(1) was called
 5828     (check-ints-equal *(edx+4) 2 "F - test-add-with-too-many-inouts: exit status")
 5829     # don't restore from ebp
 5830     81 0/subop/add %esp 8/imm32
 5831     # . epilogue
 5832     5d/pop-to-ebp
 5833     c3/return
 5834 
 5835 test-add-with-too-many-inouts-2:
 5836     # . prologue
 5837     55/push-ebp
 5838     89/<- %ebp 4/r32/esp
 5839     # setup
 5840     (clear-stream _test-input-stream)
 5841     (clear-stream $_test-input-buffered-file->buffer)
 5842     (clear-stream _test-output-stream)
 5843     (clear-stream $_test-output-buffered-file->buffer)
 5844     (clear-stream _test-error-stream)
 5845     (clear-stream $_test-error-buffered-file->buffer)
 5846     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 5847     68/push 0/imm32
 5848     68/push 0/imm32
 5849     89/<- %edx 4/r32/esp
 5850     (tailor-exit-descriptor %edx 0x10)
 5851     #
 5852     (write _test-input-stream "fn foo {\n")
 5853     (write _test-input-stream "  var a: int\n")
 5854     (write _test-input-stream "  add-to a, 0, 1\n")
 5855     (write _test-input-stream "}\n")
 5856     # convert
 5857     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 5858     # registers except esp clobbered at this point
 5859     # restore ed
 5860     89/<- %edx 4/r32/esp
 5861     (flush _test-output-buffered-file)
 5862     (flush _test-error-buffered-file)
 5863 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5869     # check output
 5870     (check-stream-equal _test-output-stream  ""  "F - test-add-with-too-many-inouts-2: output should be empty")
 5871     (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")
 5872     # check that stop(1) was called
 5873     (check-ints-equal *(edx+4) 2 "F - test-add-with-too-many-inouts-2: exit status")
 5874     # don't restore from ebp
 5875     81 0/subop/add %esp 8/imm32
 5876     # . epilogue
 5877     5d/pop-to-ebp
 5878     c3/return
 5879 
 5880 test-add-with-too-many-outputs:
 5881     # . prologue
 5882     55/push-ebp
 5883     89/<- %ebp 4/r32/esp
 5884     # setup
 5885     (clear-stream _test-input-stream)
 5886     (clear-stream $_test-input-buffered-file->buffer)
 5887     (clear-stream _test-output-stream)
 5888     (clear-stream $_test-output-buffered-file->buffer)
 5889     (clear-stream _test-error-stream)
 5890     (clear-stream $_test-error-buffered-file->buffer)
 5891     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 5892     68/push 0/imm32
 5893     68/push 0/imm32
 5894     89/<- %edx 4/r32/esp
 5895     (tailor-exit-descriptor %edx 0x10)
 5896     #
 5897     (write _test-input-stream "fn foo {\n")
 5898     (write _test-input-stream "  var a/eax: int <- copy 0\n")
 5899     (write _test-input-stream "  var b/ebx: int <- copy 0\n")
 5900     (write _test-input-stream "  var c/ecx: int <- copy 0\n")
 5901     (write _test-input-stream "  c, b <- add a\n")
 5902     (write _test-input-stream "}\n")
 5903     # convert
 5904     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 5905     # registers except esp clobbered at this point
 5906     # restore ed
 5907     89/<- %edx 4/r32/esp
 5908     (flush _test-output-buffered-file)
 5909     (flush _test-error-buffered-file)
 5910 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5916     # check output
 5917     (check-stream-equal _test-output-stream  ""  "F - test-add-with-too-many-outputs: output should be empty")
 5918     (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")
 5919     # check that stop(1) was called
 5920     (check-ints-equal *(edx+4) 2 "F - test-add-with-too-many-outputs: exit status")
 5921     # don't restore from ebp
 5922     81 0/subop/add %esp 8/imm32
 5923     # . epilogue
 5924     5d/pop-to-ebp
 5925     c3/return
 5926 
 5927 test-add-with-non-number:
 5928     # . prologue
 5929     55/push-ebp
 5930     89/<- %ebp 4/r32/esp
 5931     # setup
 5932     (clear-stream _test-input-stream)
 5933     (clear-stream $_test-input-buffered-file->buffer)
 5934     (clear-stream _test-output-stream)
 5935     (clear-stream $_test-output-buffered-file->buffer)
 5936     (clear-stream _test-error-stream)
 5937     (clear-stream $_test-error-buffered-file->buffer)
 5938     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 5939     68/push 0/imm32
 5940     68/push 0/imm32
 5941     89/<- %edx 4/r32/esp
 5942     (tailor-exit-descriptor %edx 0x10)
 5943     #
 5944     (write _test-input-stream "fn foo {\n")
 5945     (write _test-input-stream "  var a: int\n")
 5946     (write _test-input-stream "  var b/ecx: (addr int) <- add a\n")
 5947     (write _test-input-stream "}\n")
 5948     # convert
 5949     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 5950     # registers except esp clobbered at this point
 5951     # restore ed
 5952     89/<- %edx 4/r32/esp
 5953     (flush _test-output-buffered-file)
 5954     (flush _test-error-buffered-file)
 5955 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5961     # check output
 5962     (check-stream-equal _test-output-stream  ""  "F - test-add-with-non-number: output should be empty")
 5963     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt add: only non-addr scalar args permitted"  "F - test-add-with-non-number: error message")
 5964     # check that stop(1) was called
 5965     (check-ints-equal *(edx+4) 2 "F - test-add-with-non-number: exit status")
 5966     # don't restore from ebp
 5967     81 0/subop/add %esp 8/imm32
 5968     # . epilogue
 5969     5d/pop-to-ebp
 5970     c3/return
 5971 
 5972 test-add-with-addr-dereferenced:
 5973     # . prologue
 5974     55/push-ebp
 5975     89/<- %ebp 4/r32/esp
 5976     # setup
 5977     (clear-stream _test-input-stream)
 5978     (clear-stream $_test-input-buffered-file->buffer)
 5979     (clear-stream _test-output-stream)
 5980     (clear-stream $_test-output-buffered-file->buffer)
 5981     #
 5982     (write _test-input-stream "fn foo {\n")
 5983     (write _test-input-stream "  var a/eax: (addr int) <- copy 0\n")
 5984     (write _test-input-stream "  add-to *a, 1\n")
 5985     (write _test-input-stream "}\n")
 5986     # convert
 5987     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5988     (flush _test-output-buffered-file)
 5989     # no error
 5990     # . epilogue
 5991     89/<- %esp 5/r32/ebp
 5992     5d/pop-to-ebp
 5993     c3/return
 5994 
 5995 test-get-with-wrong-field:
 5996     # . prologue
 5997     55/push-ebp
 5998     89/<- %ebp 4/r32/esp
 5999     # setup
 6000     (clear-stream _test-input-stream)
 6001     (clear-stream $_test-input-buffered-file->buffer)
 6002     (clear-stream _test-output-stream)
 6003     (clear-stream $_test-output-buffered-file->buffer)
 6004     (clear-stream _test-error-stream)
 6005     (clear-stream $_test-error-buffered-file->buffer)
 6006     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6007     68/push 0/imm32
 6008     68/push 0/imm32
 6009     89/<- %edx 4/r32/esp
 6010     (tailor-exit-descriptor %edx 0x10)
 6011     #
 6012     (write _test-input-stream "fn foo {\n")
 6013     (write _test-input-stream "  var a: t\n")
 6014     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 6015     (write _test-input-stream "}\n")
 6016     (write _test-input-stream "type t {\n")
 6017     (write _test-input-stream "  x: int\n")
 6018     (write _test-input-stream "}\n")
 6019     # convert
 6020     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6021     # registers except esp clobbered at this point
 6022     # restore ed
 6023     89/<- %edx 4/r32/esp
 6024     (flush _test-output-buffered-file)
 6025     (flush _test-error-buffered-file)
 6026 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6032     # check output
 6033     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-field: output should be empty")
 6034     (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")
 6035     # check that stop(1) was called
 6036     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-field: exit status")
 6037     # don't restore from ebp
 6038     81 0/subop/add %esp 8/imm32
 6039     # . epilogue
 6040     5d/pop-to-ebp
 6041     c3/return
 6042 
 6043 test-get-with-wrong-base-type:
 6044     # . prologue
 6045     55/push-ebp
 6046     89/<- %ebp 4/r32/esp
 6047     # setup
 6048     (clear-stream _test-input-stream)
 6049     (clear-stream $_test-input-buffered-file->buffer)
 6050     (clear-stream _test-output-stream)
 6051     (clear-stream $_test-output-buffered-file->buffer)
 6052     (clear-stream _test-error-stream)
 6053     (clear-stream $_test-error-buffered-file->buffer)
 6054     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6055     68/push 0/imm32
 6056     68/push 0/imm32
 6057     89/<- %edx 4/r32/esp
 6058     (tailor-exit-descriptor %edx 0x10)
 6059     #
 6060     (write _test-input-stream "fn foo {\n")
 6061     (write _test-input-stream "  var a: int\n")
 6062     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 6063     (write _test-input-stream "}\n")
 6064     # convert
 6065     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6066     # registers except esp clobbered at this point
 6067     # restore ed
 6068     89/<- %edx 4/r32/esp
 6069     (flush _test-output-buffered-file)
 6070     (flush _test-error-buffered-file)
 6071 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6077     # check output
 6078     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-base-type: output should be empty")
 6079     (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")
 6080     # check that stop(1) was called
 6081     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-base-type: exit status")
 6082     # don't restore from ebp
 6083     81 0/subop/add %esp 8/imm32
 6084     # . epilogue
 6085     5d/pop-to-ebp
 6086     c3/return
 6087 
 6088 test-get-with-wrong-base-type-2:
 6089     # . prologue
 6090     55/push-ebp
 6091     89/<- %ebp 4/r32/esp
 6092     # setup
 6093     (clear-stream _test-input-stream)
 6094     (clear-stream $_test-input-buffered-file->buffer)
 6095     (clear-stream _test-output-stream)
 6096     (clear-stream $_test-output-buffered-file->buffer)
 6097     (clear-stream _test-error-stream)
 6098     (clear-stream $_test-error-buffered-file->buffer)
 6099     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6100     68/push 0/imm32
 6101     68/push 0/imm32
 6102     89/<- %edx 4/r32/esp
 6103     (tailor-exit-descriptor %edx 0x10)
 6104     #
 6105     (write _test-input-stream "fn foo {\n")
 6106     (write _test-input-stream "  var a: (addr t)\n")
 6107     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 6108     (write _test-input-stream "}\n")
 6109     (write _test-input-stream "type t {\n")
 6110     (write _test-input-stream "  x: int\n")
 6111     (write _test-input-stream "}\n")
 6112     # convert
 6113     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6114     # registers except esp clobbered at this point
 6115     # restore ed
 6116     89/<- %edx 4/r32/esp
 6117     (flush _test-output-buffered-file)
 6118     (flush _test-error-buffered-file)
 6119 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6125     # check output
 6126     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-base-type-2: output should be empty")
 6127     (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")
 6128     # check that stop(1) was called
 6129     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-base-type-2: exit status")
 6130     # don't restore from ebp
 6131     81 0/subop/add %esp 8/imm32
 6132     # . epilogue
 6133     5d/pop-to-ebp
 6134     c3/return
 6135 
 6136 test-get-with-wrong-offset-type:
 6137     # . prologue
 6138     55/push-ebp
 6139     89/<- %ebp 4/r32/esp
 6140     # setup
 6141     (clear-stream _test-input-stream)
 6142     (clear-stream $_test-input-buffered-file->buffer)
 6143     (clear-stream _test-output-stream)
 6144     (clear-stream $_test-output-buffered-file->buffer)
 6145     (clear-stream _test-error-stream)
 6146     (clear-stream $_test-error-buffered-file->buffer)
 6147     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6148     68/push 0/imm32
 6149     68/push 0/imm32
 6150     89/<- %edx 4/r32/esp
 6151     (tailor-exit-descriptor %edx 0x10)
 6152     #
 6153     (write _test-input-stream "fn foo {\n")
 6154     (write _test-input-stream "  var a: t\n")
 6155     (write _test-input-stream "  var b: int\n")
 6156     (write _test-input-stream "  var c/ecx: (addr int) <- get a, b\n")
 6157     (write _test-input-stream "}\n")
 6158     (write _test-input-stream "type t {\n")
 6159     (write _test-input-stream "  x: int\n")
 6160     (write _test-input-stream "}\n")
 6161     # convert
 6162     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6163     # registers except esp clobbered at this point
 6164     # restore ed
 6165     89/<- %edx 4/r32/esp
 6166     (flush _test-output-buffered-file)
 6167     (flush _test-error-buffered-file)
 6168 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6174     # check output
 6175     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-offset-type: output should be empty")
 6176     (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")
 6177     # check that stop(1) was called
 6178     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-offset-type: exit status")
 6179     # don't restore from ebp
 6180     81 0/subop/add %esp 8/imm32
 6181     # . epilogue
 6182     5d/pop-to-ebp
 6183     c3/return
 6184 
 6185 test-get-with-wrong-output-type:
 6186     # . prologue
 6187     55/push-ebp
 6188     89/<- %ebp 4/r32/esp
 6189     # setup
 6190     (clear-stream _test-input-stream)
 6191     (clear-stream $_test-input-buffered-file->buffer)
 6192     (clear-stream _test-output-stream)
 6193     (clear-stream $_test-output-buffered-file->buffer)
 6194     (clear-stream _test-error-stream)
 6195     (clear-stream $_test-error-buffered-file->buffer)
 6196     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6197     68/push 0/imm32
 6198     68/push 0/imm32
 6199     89/<- %edx 4/r32/esp
 6200     (tailor-exit-descriptor %edx 0x10)
 6201     #
 6202     (write _test-input-stream "fn foo {\n")
 6203     (write _test-input-stream "  var a: t\n")
 6204     (write _test-input-stream "  var c: (addr int)\n")
 6205     (write _test-input-stream "  c <- get a, x\n")
 6206     (write _test-input-stream "}\n")
 6207     (write _test-input-stream "type t {\n")
 6208     (write _test-input-stream "  x: int\n")
 6209     (write _test-input-stream "}\n")
 6210     # convert
 6211     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6212     # registers except esp clobbered at this point
 6213     # restore ed
 6214     89/<- %edx 4/r32/esp
 6215     (flush _test-output-buffered-file)
 6216     (flush _test-error-buffered-file)
 6217 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6223     # check output
 6224     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type: output should be empty")
 6225     (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")
 6226     # check that stop(1) was called
 6227     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type: exit status")
 6228     # don't restore from ebp
 6229     81 0/subop/add %esp 8/imm32
 6230     # . epilogue
 6231     5d/pop-to-ebp
 6232     c3/return
 6233 
 6234 test-get-with-wrong-output-type-2:
 6235     # . prologue
 6236     55/push-ebp
 6237     89/<- %ebp 4/r32/esp
 6238     # setup
 6239     (clear-stream _test-input-stream)
 6240     (clear-stream $_test-input-buffered-file->buffer)
 6241     (clear-stream _test-output-stream)
 6242     (clear-stream $_test-output-buffered-file->buffer)
 6243     (clear-stream _test-error-stream)
 6244     (clear-stream $_test-error-buffered-file->buffer)
 6245     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6246     68/push 0/imm32
 6247     68/push 0/imm32
 6248     89/<- %edx 4/r32/esp
 6249     (tailor-exit-descriptor %edx 0x10)
 6250     #
 6251     (write _test-input-stream "fn foo {\n")
 6252     (write _test-input-stream "  var a: t\n")
 6253     (write _test-input-stream "  var c/ecx: int <- get a, x\n")
 6254     (write _test-input-stream "}\n")
 6255     (write _test-input-stream "type t {\n")
 6256     (write _test-input-stream "  x: int\n")
 6257     (write _test-input-stream "}\n")
 6258     # convert
 6259     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6260     # registers except esp clobbered at this point
 6261     # restore ed
 6262     89/<- %edx 4/r32/esp
 6263     (flush _test-output-buffered-file)
 6264     (flush _test-error-buffered-file)
 6265 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6271     # check output
 6272     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type-2: output should be empty")
 6273     (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")
 6274     # check that stop(1) was called
 6275     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type-2: exit status")
 6276     # don't restore from ebp
 6277     81 0/subop/add %esp 8/imm32
 6278     # . epilogue
 6279     5d/pop-to-ebp
 6280     c3/return
 6281 
 6282 test-get-with-wrong-output-type-3:
 6283     # . prologue
 6284     55/push-ebp
 6285     89/<- %ebp 4/r32/esp
 6286     # setup
 6287     (clear-stream _test-input-stream)
 6288     (clear-stream $_test-input-buffered-file->buffer)
 6289     (clear-stream _test-output-stream)
 6290     (clear-stream $_test-output-buffered-file->buffer)
 6291     (clear-stream _test-error-stream)
 6292     (clear-stream $_test-error-buffered-file->buffer)
 6293     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6294     68/push 0/imm32
 6295     68/push 0/imm32
 6296     89/<- %edx 4/r32/esp
 6297     (tailor-exit-descriptor %edx 0x10)
 6298     #
 6299     (write _test-input-stream "fn foo {\n")
 6300     (write _test-input-stream "  var a: t\n")
 6301     (write _test-input-stream "  var c/ecx: (array int) <- get a, x\n")
 6302     (write _test-input-stream "}\n")
 6303     (write _test-input-stream "type t {\n")
 6304     (write _test-input-stream "  x: int\n")
 6305     (write _test-input-stream "}\n")
 6306     # convert
 6307     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6308     # registers except esp clobbered at this point
 6309     # restore ed
 6310     89/<- %edx 4/r32/esp
 6311     (flush _test-output-buffered-file)
 6312     (flush _test-error-buffered-file)
 6313 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6319     # check output
 6320     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type-3: output should be empty")
 6321     (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")
 6322     # check that stop(1) was called
 6323     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type-3: exit status")
 6324     # don't restore from ebp
 6325     81 0/subop/add %esp 8/imm32
 6326     # . epilogue
 6327     5d/pop-to-ebp
 6328     c3/return
 6329 
 6330 test-get-with-wrong-output-type-4:
 6331     # . prologue
 6332     55/push-ebp
 6333     89/<- %ebp 4/r32/esp
 6334     # setup
 6335     (clear-stream _test-input-stream)
 6336     (clear-stream $_test-input-buffered-file->buffer)
 6337     (clear-stream _test-output-stream)
 6338     (clear-stream $_test-output-buffered-file->buffer)
 6339     (clear-stream _test-error-stream)
 6340     (clear-stream $_test-error-buffered-file->buffer)
 6341     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6342     68/push 0/imm32
 6343     68/push 0/imm32
 6344     89/<- %edx 4/r32/esp
 6345     (tailor-exit-descriptor %edx 0x10)
 6346     #
 6347     (write _test-input-stream "fn foo {\n")
 6348     (write _test-input-stream "  var a: t\n")
 6349     (write _test-input-stream "  var c/ecx: (addr boolean) <- get a, x\n")
 6350     (write _test-input-stream "}\n")
 6351     (write _test-input-stream "type t {\n")
 6352     (write _test-input-stream "  x: int\n")
 6353     (write _test-input-stream "}\n")
 6354     # convert
 6355     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6356     # registers except esp clobbered at this point
 6357     # restore ed
 6358     89/<- %edx 4/r32/esp
 6359     (flush _test-output-buffered-file)
 6360     (flush _test-error-buffered-file)
 6361 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6367     # check output
 6368     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type-4: output should be empty")
 6369     (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")
 6370     # check that stop(1) was called
 6371     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type-4: exit status")
 6372     # don't restore from ebp
 6373     81 0/subop/add %esp 8/imm32
 6374     # . epilogue
 6375     5d/pop-to-ebp
 6376     c3/return
 6377 
 6378 test-get-with-wrong-output-type-5:
 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 a: t\n")
 6390     (write _test-input-stream "  var c/ecx: (addr handle int) <- get a, x\n")
 6391     (write _test-input-stream "}\n")
 6392     (write _test-input-stream "type t {\n")
 6393     (write _test-input-stream "  x: (handle int)\n")
 6394     (write _test-input-stream "}\n")
 6395     # convert
 6396     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6397     (flush _test-output-buffered-file)
 6398     # no errors
 6399     # . epilogue
 6400     89/<- %esp 5/r32/ebp
 6401     5d/pop-to-ebp
 6402     c3/return
 6403 
 6404 test-get-with-too-few-inouts:
 6405     # . prologue
 6406     55/push-ebp
 6407     89/<- %ebp 4/r32/esp
 6408     # setup
 6409     (clear-stream _test-input-stream)
 6410     (clear-stream $_test-input-buffered-file->buffer)
 6411     (clear-stream _test-output-stream)
 6412     (clear-stream $_test-output-buffered-file->buffer)
 6413     (clear-stream _test-error-stream)
 6414     (clear-stream $_test-error-buffered-file->buffer)
 6415     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6416     68/push 0/imm32
 6417     68/push 0/imm32
 6418     89/<- %edx 4/r32/esp
 6419     (tailor-exit-descriptor %edx 0x10)
 6420     #
 6421     (write _test-input-stream "fn foo {\n")
 6422     (write _test-input-stream "  var a: t\n")
 6423     (write _test-input-stream "  var c/ecx: (addr int) <- get a\n")
 6424     (write _test-input-stream "}\n")
 6425     (write _test-input-stream "type t {\n")
 6426     (write _test-input-stream "  x: int\n")
 6427     (write _test-input-stream "}\n")
 6428     # convert
 6429     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6430     # registers except esp clobbered at this point
 6431     # restore ed
 6432     89/<- %edx 4/r32/esp
 6433     (flush _test-output-buffered-file)
 6434     (flush _test-error-buffered-file)
 6435 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6441     # check output
 6442     (check-stream-equal _test-output-stream  ""  "F - test-get-with-too-few-inouts: output should be empty")
 6443     (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")
 6444     # check that stop(1) was called
 6445     (check-ints-equal *(edx+4) 2 "F - test-get-with-too-few-inouts: exit status")
 6446     # don't restore from ebp
 6447     81 0/subop/add %esp 8/imm32
 6448     # . epilogue
 6449     5d/pop-to-ebp
 6450     c3/return
 6451 
 6452 test-get-with-too-many-inouts:
 6453     # . prologue
 6454     55/push-ebp
 6455     89/<- %ebp 4/r32/esp
 6456     # setup
 6457     (clear-stream _test-input-stream)
 6458     (clear-stream $_test-input-buffered-file->buffer)
 6459     (clear-stream _test-output-stream)
 6460     (clear-stream $_test-output-buffered-file->buffer)
 6461     (clear-stream _test-error-stream)
 6462     (clear-stream $_test-error-buffered-file->buffer)
 6463     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6464     68/push 0/imm32
 6465     68/push 0/imm32
 6466     89/<- %edx 4/r32/esp
 6467     (tailor-exit-descriptor %edx 0x10)
 6468     #
 6469     (write _test-input-stream "fn foo {\n")
 6470     (write _test-input-stream "  var a: t\n")
 6471     (write _test-input-stream "  var c/ecx: (addr int) <- get a, x, 0\n")
 6472     (write _test-input-stream "}\n")
 6473     (write _test-input-stream "type t {\n")
 6474     (write _test-input-stream "  x: int\n")
 6475     (write _test-input-stream "}\n")
 6476     # convert
 6477     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6478     # registers except esp clobbered at this point
 6479     # restore ed
 6480     89/<- %edx 4/r32/esp
 6481     (flush _test-output-buffered-file)
 6482     (flush _test-error-buffered-file)
 6483 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6489     # check output
 6490     (check-stream-equal _test-output-stream  ""  "F - test-get-with-too-many-inouts: output should be empty")
 6491     (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")
 6492     # check that stop(1) was called
 6493     (check-ints-equal *(edx+4) 2 "F - test-get-with-too-many-inouts: exit status")
 6494     # don't restore from ebp
 6495     81 0/subop/add %esp 8/imm32
 6496     # . epilogue
 6497     5d/pop-to-ebp
 6498     c3/return
 6499 
 6500 test-get-with-no-output:
 6501     # . prologue
 6502     55/push-ebp
 6503     89/<- %ebp 4/r32/esp
 6504     # setup
 6505     (clear-stream _test-input-stream)
 6506     (clear-stream $_test-input-buffered-file->buffer)
 6507     (clear-stream _test-output-stream)
 6508     (clear-stream $_test-output-buffered-file->buffer)
 6509     (clear-stream _test-error-stream)
 6510     (clear-stream $_test-error-buffered-file->buffer)
 6511     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6512     68/push 0/imm32
 6513     68/push 0/imm32
 6514     89/<- %edx 4/r32/esp
 6515     (tailor-exit-descriptor %edx 0x10)
 6516     #
 6517     (write _test-input-stream "fn foo {\n")
 6518     (write _test-input-stream "  var a: t\n")
 6519     (write _test-input-stream "  get a, x\n")
 6520     (write _test-input-stream "}\n")
 6521     (write _test-input-stream "type t {\n")
 6522     (write _test-input-stream "  x: int\n")
 6523     (write _test-input-stream "}\n")
 6524     # convert
 6525     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6526     # registers except esp clobbered at this point
 6527     # restore ed
 6528     89/<- %edx 4/r32/esp
 6529     (flush _test-output-buffered-file)
 6530     (flush _test-error-buffered-file)
 6531 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6537     # check output
 6538     (check-stream-equal _test-output-stream  ""  "F - test-get-with-no-output: output should be empty")
 6539     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt get: must have an output"  "F - test-get-with-no-output: error message")
 6540     # check that stop(1) was called
 6541     (check-ints-equal *(edx+4) 2 "F - test-get-with-no-output: exit status")
 6542     # don't restore from ebp
 6543     81 0/subop/add %esp 8/imm32
 6544     # . epilogue
 6545     5d/pop-to-ebp
 6546     c3/return
 6547 
 6548 test-get-with-too-many-outputs:
 6549     # . prologue
 6550     55/push-ebp
 6551     89/<- %ebp 4/r32/esp
 6552     # setup
 6553     (clear-stream _test-input-stream)
 6554     (clear-stream $_test-input-buffered-file->buffer)
 6555     (clear-stream _test-output-stream)
 6556     (clear-stream $_test-output-buffered-file->buffer)
 6557     (clear-stream _test-error-stream)
 6558     (clear-stream $_test-error-buffered-file->buffer)
 6559     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6560     68/push 0/imm32
 6561     68/push 0/imm32
 6562     89/<- %edx 4/r32/esp
 6563     (tailor-exit-descriptor %edx 0x10)
 6564     #
 6565     (write _test-input-stream "fn foo {\n")
 6566     (write _test-input-stream "  var a: t\n")
 6567     (write _test-input-stream "  var b: int\n")
 6568     (write _test-input-stream "  var c/eax: (addr int) <- copy 0\n")
 6569     (write _test-input-stream "  c, b <- get a, x\n")
 6570     (write _test-input-stream "}\n")
 6571     (write _test-input-stream "type t {\n")
 6572     (write _test-input-stream "  x: int\n")
 6573     (write _test-input-stream "}\n")
 6574     # convert
 6575     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6576     # registers except esp clobbered at this point
 6577     # restore ed
 6578     89/<- %edx 4/r32/esp
 6579     (flush _test-output-buffered-file)
 6580     (flush _test-error-buffered-file)
 6581 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6587     # check output
 6588     (check-stream-equal _test-output-stream  ""  "F - test-get-with-too-many-outputs: output should be empty")
 6589     (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")
 6590     # check that stop(1) was called
 6591     (check-ints-equal *(edx+4) 2 "F - test-get-with-too-many-outputs: exit status")
 6592     # don't restore from ebp
 6593     81 0/subop/add %esp 8/imm32
 6594     # . epilogue
 6595     5d/pop-to-ebp
 6596     c3/return
 6597 
 6598 test-convert-array-of-user-defined-types:
 6599     # . prologue
 6600     55/push-ebp
 6601     89/<- %ebp 4/r32/esp
 6602     # setup
 6603     (clear-stream _test-input-stream)
 6604     (clear-stream $_test-input-buffered-file->buffer)
 6605     (clear-stream _test-output-stream)
 6606     (clear-stream $_test-output-buffered-file->buffer)
 6607     #
 6608     (write _test-input-stream "type t {\n")  # each t is 8 bytes, which is a power of 2
 6609     (write _test-input-stream "  x: int\n")
 6610     (write _test-input-stream "  y: int\n")
 6611     (write _test-input-stream "}\n")
 6612     (write _test-input-stream "fn foo {\n")
 6613     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
 6614     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
 6615     (write _test-input-stream "  var x/eax: (addr t) <- index arr, idx\n")
 6616     (write _test-input-stream "}\n")
 6617     # convert
 6618     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6619     (flush _test-output-buffered-file)
 6620 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6626     # check output
 6627     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-array-of-user-defined-types/0")
 6628     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-array-of-user-defined-types/1")
 6629     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-array-of-user-defined-types/2")
 6630     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-array-of-user-defined-types/3")
 6631     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-array-of-user-defined-types/4")
 6632     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-array-of-user-defined-types/5")
 6633     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-array-of-user-defined-types/6")
 6634     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-array-of-user-defined-types/7")
 6635     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-array-of-user-defined-types/8")
 6636     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-array-of-user-defined-types/9")
 6637     (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")
 6638     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-array-of-user-defined-types/13")
 6639     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-array-of-user-defined-types/14")
 6640     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-array-of-user-defined-types/15")
 6641     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-array-of-user-defined-types/16")
 6642     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-array-of-user-defined-types/17")
 6643     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-array-of-user-defined-types/18")
 6644     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-array-of-user-defined-types/19")
 6645     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-array-of-user-defined-types/20")
 6646     # . epilogue
 6647     89/<- %esp 5/r32/ebp
 6648     5d/pop-to-ebp
 6649     c3/return
 6650 
 6651 test-convert-length-of-array-of-user-defined-types-to-eax:
 6652     # . prologue
 6653     55/push-ebp
 6654     89/<- %ebp 4/r32/esp
 6655     # setup
 6656     (clear-stream _test-input-stream)
 6657     (clear-stream $_test-input-buffered-file->buffer)
 6658     (clear-stream _test-output-stream)
 6659     (clear-stream $_test-output-buffered-file->buffer)
 6660     #
 6661     (write _test-input-stream "type t {\n")  # size = 12, which is not a power of 2
 6662     (write _test-input-stream "  x: int\n")
 6663     (write _test-input-stream "  y: int\n")
 6664     (write _test-input-stream "  z: int\n")
 6665     (write _test-input-stream "}\n")
 6666     (write _test-input-stream "fn foo {\n")
 6667     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
 6668     (write _test-input-stream "  var x/eax: int <- length arr\n")
 6669     (write _test-input-stream "}\n")
 6670     # convert
 6671     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6672     (flush _test-output-buffered-file)
 6673 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6679     # check output
 6680     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types-to-eax/0")
 6681     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types-to-eax/1")
 6682     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types-to-eax/2")
 6683     (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")
 6684     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types-to-eax/4")
 6685     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types-to-eax/5")
 6686     # var arr
 6687     (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")
 6688     (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")
 6689     # length instruction
 6690     (check-next-stream-line-equal _test-output-stream "    51/push-ecx"         "F - test-convert-length-of-array-of-user-defined-types-to-eax/8")
 6691     (check-next-stream-line-equal _test-output-stream "    52/push-edx"         "F - test-convert-length-of-array-of-user-defined-types-to-eax/9")
 6692     (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")
 6693     (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")
 6694     (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")
 6695     (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")
 6696     (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")
 6697     (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")
 6698     # reclaim arr
 6699     (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")
 6700     #
 6701     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types-to-eax/17")
 6702     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types-to-eax/18")
 6703     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types-to-eax/19")
 6704     (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")
 6705     (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")
 6706     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types-to-eax/22")
 6707     # . epilogue
 6708     89/<- %esp 5/r32/ebp
 6709     5d/pop-to-ebp
 6710     c3/return
 6711 
 6712 test-convert-length-of-array-of-user-defined-types-to-ecx:
 6713     # . prologue
 6714     55/push-ebp
 6715     89/<- %ebp 4/r32/esp
 6716     # setup
 6717     (clear-stream _test-input-stream)
 6718     (clear-stream $_test-input-buffered-file->buffer)
 6719     (clear-stream _test-output-stream)
 6720     (clear-stream $_test-output-buffered-file->buffer)
 6721     #
 6722     (write _test-input-stream "type t {\n")  # size = 12, which is not a power of 2
 6723     (write _test-input-stream "  x: int\n")
 6724     (write _test-input-stream "  y: int\n")
 6725     (write _test-input-stream "  z: int\n")
 6726     (write _test-input-stream "}\n")
 6727     (write _test-input-stream "fn foo {\n")
 6728     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
 6729     (write _test-input-stream "  var x/ecx: int <- length arr\n")
 6730     (write _test-input-stream "}\n")
 6731     # convert
 6732     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6733     (flush _test-output-buffered-file)
 6734 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6740     # check output
 6741     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types-to-ecx/0")
 6742     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types-to-ecx/1")
 6743     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types-to-ecx/2")
 6744     (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")
 6745     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types-to-ecx/4")
 6746     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types-to-ecx/5")
 6747     # var a
 6748     (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")
 6749     (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")
 6750     # var x
 6751     (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")
 6752     # length instruction
 6753     (check-next-stream-line-equal _test-output-stream "    50/push-eax"         "F - test-convert-length-of-array-of-user-defined-types-to-ecx/9")
 6754     (check-next-stream-line-equal _test-output-stream "    52/push-edx"         "F - test-convert-length-of-array-of-user-defined-types-to-ecx/10")
 6755     (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")
 6756     (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")
 6757     (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")
 6758     (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")
 6759     (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")
 6760     (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")
 6761     (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")
 6762     # reclaim x
 6763     (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")
 6764     # reclaim a
 6765     (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")
 6766     #
 6767     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types-to-ecx/20")
 6768     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types-to-ecx/21")
 6769     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types-to-ecx/22")
 6770     (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")
 6771     (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")
 6772     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types-to-ecx/25")
 6773     # . epilogue
 6774     89/<- %esp 5/r32/ebp
 6775     5d/pop-to-ebp
 6776     c3/return
 6777 
 6778 test-convert-length-of-array-of-user-defined-types-to-edx:
 6779     # . prologue
 6780     55/push-ebp
 6781     89/<- %ebp 4/r32/esp
 6782     # setup
 6783     (clear-stream _test-input-stream)
 6784     (clear-stream $_test-input-buffered-file->buffer)
 6785     (clear-stream _test-output-stream)
 6786     (clear-stream $_test-output-buffered-file->buffer)
 6787     #
 6788     (write _test-input-stream "type t {\n")  # size = 12, which is not a power of 2
 6789     (write _test-input-stream "  x: int\n")
 6790     (write _test-input-stream "  y: int\n")
 6791     (write _test-input-stream "  z: int\n")
 6792     (write _test-input-stream "}\n")
 6793     (write _test-input-stream "fn foo {\n")
 6794     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
 6795     (write _test-input-stream "  var x/edx: int <- length arr\n")
 6796     (write _test-input-stream "}\n")
 6797     # convert
 6798     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6799     (flush _test-output-buffered-file)
 6800 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6806     # check output
 6807     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types-to-edx/0")
 6808     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types-to-edx/1")
 6809     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types-to-edx/2")
 6810     (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")
 6811     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types-to-edx/4")
 6812     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types-to-edx/5")
 6813     # var a
 6814     (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")
 6815     (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")
 6816     # var x
 6817     (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")
 6818     # length instruction
 6819     (check-next-stream-line-equal _test-output-stream "    50/push-eax"         "F - test-convert-length-of-array-of-user-defined-types-to-edx/9")
 6820     (check-next-stream-line-equal _test-output-stream "    51/push-ecx"         "F - test-convert-length-of-array-of-user-defined-types-to-edx/10")
 6821     (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")
 6822     (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")
 6823     (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")
 6824     (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")
 6825     (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")
 6826     (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")
 6827     (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")
 6828     # reclaim x
 6829     (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")
 6830     # reclaim a
 6831     (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")
 6832     #
 6833     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types-to-edx/20")
 6834     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types-to-edx/21")
 6835     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types-to-edx/22")
 6836     (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")
 6837     (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")
 6838     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types-to-edx/25")
 6839     # . epilogue
 6840     89/<- %esp 5/r32/ebp
 6841     5d/pop-to-ebp
 6842     c3/return
 6843 
 6844 test-convert-length-of-array-of-user-defined-types:
 6845     # . prologue
 6846     55/push-ebp
 6847     89/<- %ebp 4/r32/esp
 6848     # setup
 6849     (clear-stream _test-input-stream)
 6850     (clear-stream $_test-input-buffered-file->buffer)
 6851     (clear-stream _test-output-stream)
 6852     (clear-stream $_test-output-buffered-file->buffer)
 6853     #
 6854     (write _test-input-stream "type t {\n")  # each t is 8 bytes, which is a power of 2
 6855     (write _test-input-stream "  x: int\n")
 6856     (write _test-input-stream "  y: int\n")
 6857     (write _test-input-stream "  z: int\n")
 6858     (write _test-input-stream "}\n")
 6859     (write _test-input-stream "fn foo {\n")
 6860     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
 6861     (write _test-input-stream "  var x/ebx: int <- length arr\n")
 6862     (write _test-input-stream "}\n")
 6863     # convert
 6864     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6865     (flush _test-output-buffered-file)
 6866 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6872     # check output
 6873     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types/0")
 6874     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types/1")
 6875     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types/2")
 6876     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array-of-user-defined-types/3")
 6877     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types/4")
 6878     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types/5")
 6879     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array-of-user-defined-types/6")
 6880     (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")
 6881     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ebx"  "F - test-convert-length-of-array-of-user-defined-types/8")
 6882     (check-next-stream-line-equal _test-output-stream "    50/push-eax"         "F - test-convert-length-of-array-of-user-defined-types/9")
 6883     (check-next-stream-line-equal _test-output-stream "    51/push-ecx"         "F - test-convert-length-of-array-of-user-defined-types/10")
 6884     (check-next-stream-line-equal _test-output-stream "    52/push-edx"         "F - test-convert-length-of-array-of-user-defined-types/11")
 6885     (check-next-stream-line-equal _test-output-stream "    8b/-> *eax 0x00000000/r32"  "F - test-convert-length-of-array-of-user-defined-types/12")
 6886     (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")
 6887     (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")
 6888     (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")
 6889     (check-next-stream-line-equal _test-output-stream "    89/<- %ebx 0/r32/eax"  "F - test-convert-length-of-array-of-user-defined-types/16")
 6890     (check-next-stream-line-equal _test-output-stream "    5a/pop-to-edx"       "F - test-convert-length-of-array-of-user-defined-types/17")
 6891     (check-next-stream-line-equal _test-output-stream "    59/pop-to-ecx"       "F - test-convert-length-of-array-of-user-defined-types/18")
 6892     (check-next-stream-line-equal _test-output-stream "    58/pop-to-eax"       "F - test-convert-length-of-array-of-user-defined-types/19")
 6893     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ebx"  "F - test-convert-length-of-array-of-user-defined-types/20")
 6894     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array-of-user-defined-types/21")
 6895     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types/22")
 6896     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types/23")
 6897     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types/24")
 6898     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array-of-user-defined-types/25")
 6899     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array-of-user-defined-types/26")
 6900     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types/27")
 6901     # . epilogue
 6902     89/<- %esp 5/r32/ebp
 6903     5d/pop-to-ebp
 6904     c3/return
 6905 
 6906 test-index-with-non-array-atom-base-type:
 6907     # . prologue
 6908     55/push-ebp
 6909     89/<- %ebp 4/r32/esp
 6910     # setup
 6911     (clear-stream _test-input-stream)
 6912     (clear-stream $_test-input-buffered-file->buffer)
 6913     (clear-stream _test-output-stream)
 6914     (clear-stream $_test-output-buffered-file->buffer)
 6915     (clear-stream _test-error-stream)
 6916     (clear-stream $_test-error-buffered-file->buffer)
 6917     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6918     68/push 0/imm32
 6919     68/push 0/imm32
 6920     89/<- %edx 4/r32/esp
 6921     (tailor-exit-descriptor %edx 0x10)
 6922     #
 6923     (write _test-input-stream "fn foo {\n")
 6924     (write _test-input-stream "  var a: int\n")
 6925     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
 6926     (write _test-input-stream "}\n")
 6927     # convert
 6928     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6929     # registers except esp clobbered at this point
 6930     # restore ed
 6931     89/<- %edx 4/r32/esp
 6932     (flush _test-output-buffered-file)
 6933     (flush _test-error-buffered-file)
 6934 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6940     # check output
 6941     (check-stream-equal _test-output-stream  ""  "F - test-index-with-non-array-atom-base-type: output should be empty")
 6942     (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")
 6943     # check that stop(1) was called
 6944     (check-ints-equal *(edx+4) 2 "F - test-index-with-non-array-atom-base-type: exit status")
 6945     # don't restore from ebp
 6946     81 0/subop/add %esp 8/imm32
 6947     # . epilogue
 6948     5d/pop-to-ebp
 6949     c3/return
 6950 
 6951 test-index-with-non-array-compound-base-type:
 6952     # . prologue
 6953     55/push-ebp
 6954     89/<- %ebp 4/r32/esp
 6955     # setup
 6956     (clear-stream _test-input-stream)
 6957     (clear-stream $_test-input-buffered-file->buffer)
 6958     (clear-stream _test-output-stream)
 6959     (clear-stream $_test-output-buffered-file->buffer)
 6960     (clear-stream _test-error-stream)
 6961     (clear-stream $_test-error-buffered-file->buffer)
 6962     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6963     68/push 0/imm32
 6964     68/push 0/imm32
 6965     89/<- %edx 4/r32/esp
 6966     (tailor-exit-descriptor %edx 0x10)
 6967     #
 6968     (write _test-input-stream "fn foo {\n")
 6969     (write _test-input-stream "  var a: (handle int)\n")
 6970     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
 6971     (write _test-input-stream "}\n")
 6972     # convert
 6973     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6974     # registers except esp clobbered at this point
 6975     # restore ed
 6976     89/<- %edx 4/r32/esp
 6977     (flush _test-output-buffered-file)
 6978     (flush _test-error-buffered-file)
 6979 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6985     # check output
 6986     (check-stream-equal _test-output-stream  ""  "F - test-index-with-non-array-compound-base-type: output should be empty")
 6987     (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")
 6988     # check that stop(1) was called
 6989     (check-ints-equal *(edx+4) 2 "F - test-index-with-non-array-compound-base-type: exit status")
 6990     # don't restore from ebp
 6991     81 0/subop/add %esp 8/imm32
 6992     # . epilogue
 6993     5d/pop-to-ebp
 6994     c3/return
 6995 
 6996 test-index-with-non-array-compound-base-type-2:
 6997     # . prologue
 6998     55/push-ebp
 6999     89/<- %ebp 4/r32/esp
 7000     # setup
 7001     (clear-stream _test-input-stream)
 7002     (clear-stream $_test-input-buffered-file->buffer)
 7003     (clear-stream _test-output-stream)
 7004     (clear-stream $_test-output-buffered-file->buffer)
 7005     (clear-stream _test-error-stream)
 7006     (clear-stream $_test-error-buffered-file->buffer)
 7007     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7008     68/push 0/imm32
 7009     68/push 0/imm32
 7010     89/<- %edx 4/r32/esp
 7011     (tailor-exit-descriptor %edx 0x10)
 7012     #
 7013     (write _test-input-stream "fn foo {\n")
 7014     (write _test-input-stream "  var a: (addr int)\n")
 7015     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
 7016     (write _test-input-stream "}\n")
 7017     # convert
 7018     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7019     # registers except esp clobbered at this point
 7020     # restore ed
 7021     89/<- %edx 4/r32/esp
 7022     (flush _test-output-buffered-file)
 7023     (flush _test-error-buffered-file)
 7024 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7030     # check output
 7031     (check-stream-equal _test-output-stream  ""  "F - test-index-with-non-array-compound-base-type-2: output should be empty")
 7032     (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")
 7033     # check that stop(1) was called
 7034     (check-ints-equal *(edx+4) 2 "F - test-index-with-non-array-compound-base-type-2: exit status")
 7035     # don't restore from ebp
 7036     81 0/subop/add %esp 8/imm32
 7037     # . epilogue
 7038     5d/pop-to-ebp
 7039     c3/return
 7040 
 7041 test-index-with-array-atom-base-type:
 7042     # . prologue
 7043     55/push-ebp
 7044     89/<- %ebp 4/r32/esp
 7045     # setup
 7046     (clear-stream _test-input-stream)
 7047     (clear-stream $_test-input-buffered-file->buffer)
 7048     (clear-stream _test-output-stream)
 7049     (clear-stream $_test-output-buffered-file->buffer)
 7050     (clear-stream _test-error-stream)
 7051     (clear-stream $_test-error-buffered-file->buffer)
 7052     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7053     68/push 0/imm32
 7054     68/push 0/imm32
 7055     89/<- %edx 4/r32/esp
 7056     (tailor-exit-descriptor %edx 0x10)
 7057     #
 7058     (write _test-input-stream "fn foo {\n")
 7059     (write _test-input-stream "  var a: array\n")
 7060     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
 7061     (write _test-input-stream "}\n")
 7062     # convert
 7063     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7064     # registers except esp clobbered at this point
 7065     # restore ed
 7066     89/<- %edx 4/r32/esp
 7067     (flush _test-output-buffered-file)
 7068     (flush _test-error-buffered-file)
 7069 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7075     # check output
 7076     (check-stream-equal _test-output-stream  ""  "F - test-index-with-array-atom-base-type: output should be empty")
 7077     (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")
 7078     # check that stop(1) was called
 7079     (check-ints-equal *(edx+4) 2 "F - test-index-with-array-atom-base-type: exit status")
 7080     # don't restore from ebp
 7081     81 0/subop/add %esp 8/imm32
 7082     # . epilogue
 7083     5d/pop-to-ebp
 7084     c3/return
 7085 
 7086 test-index-with-addr-base-on-stack:
 7087     # . prologue
 7088     55/push-ebp
 7089     89/<- %ebp 4/r32/esp
 7090     # setup
 7091     (clear-stream _test-input-stream)
 7092     (clear-stream $_test-input-buffered-file->buffer)
 7093     (clear-stream _test-output-stream)
 7094     (clear-stream $_test-output-buffered-file->buffer)
 7095     (clear-stream _test-error-stream)
 7096     (clear-stream $_test-error-buffered-file->buffer)
 7097     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7098     68/push 0/imm32
 7099     68/push 0/imm32
 7100     89/<- %edx 4/r32/esp
 7101     (tailor-exit-descriptor %edx 0x10)
 7102     #
 7103     (write _test-input-stream "fn foo {\n")
 7104     (write _test-input-stream "  var a: (addr array int)\n")
 7105     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
 7106     (write _test-input-stream "}\n")
 7107     # convert
 7108     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7109     # registers except esp clobbered at this point
 7110     # restore ed
 7111     89/<- %edx 4/r32/esp
 7112     (flush _test-output-buffered-file)
 7113     (flush _test-error-buffered-file)
 7114 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7120     # check output
 7121     (check-stream-equal _test-output-stream  ""  "F - test-index-with-addr-base-on-stack: output should be empty")
 7122     (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")
 7123     # check that stop(1) was called
 7124     (check-ints-equal *(edx+4) 2 "F - test-index-with-addr-base-on-stack: exit status")
 7125     # don't restore from ebp
 7126     81 0/subop/add %esp 8/imm32
 7127     # . epilogue
 7128     5d/pop-to-ebp
 7129     c3/return
 7130 
 7131 test-index-with-array-base-in-register:
 7132     # . prologue
 7133     55/push-ebp
 7134     89/<- %ebp 4/r32/esp
 7135     # setup
 7136     (clear-stream _test-input-stream)
 7137     (clear-stream $_test-input-buffered-file->buffer)
 7138     (clear-stream _test-output-stream)
 7139     (clear-stream $_test-output-buffered-file->buffer)
 7140     (clear-stream _test-error-stream)
 7141     (clear-stream $_test-error-buffered-file->buffer)
 7142     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7143     68/push 0/imm32
 7144     68/push 0/imm32
 7145     89/<- %edx 4/r32/esp
 7146     (tailor-exit-descriptor %edx 0x10)
 7147     #
 7148     (write _test-input-stream "fn foo {\n")
 7149     (write _test-input-stream "  var a/eax: (array int 3) <- copy 0\n")
 7150     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
 7151     (write _test-input-stream "}\n")
 7152     # convert
 7153     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7154     # registers except esp clobbered at this point
 7155     # restore ed
 7156     89/<- %edx 4/r32/esp
 7157     (flush _test-output-buffered-file)
 7158     (flush _test-error-buffered-file)
 7159 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7165     # check output
 7166     (check-stream-equal _test-output-stream  ""  "F - test-index-with-array-base-in-register: output should be empty")
 7167     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: var 'a' is an array, and so must live on the stack"  "F - test-index-with-array-base-in-register: error message")
 7168     # check that stop(1) was called
 7169     (check-ints-equal *(edx+4) 2 "F - test-index-with-array-base-in-register: exit status")
 7170     # don't restore from ebp
 7171     81 0/subop/add %esp 8/imm32
 7172     # . epilogue
 7173     5d/pop-to-ebp
 7174     c3/return
 7175 
 7176 test-index-with-wrong-index-type:
 7177     # . prologue
 7178     55/push-ebp
 7179     89/<- %ebp 4/r32/esp
 7180     # setup
 7181     (clear-stream _test-input-stream)
 7182     (clear-stream $_test-input-buffered-file->buffer)
 7183     (clear-stream _test-output-stream)
 7184     (clear-stream $_test-output-buffered-file->buffer)
 7185     (clear-stream _test-error-stream)
 7186     (clear-stream $_test-error-buffered-file->buffer)
 7187     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7188     68/push 0/imm32
 7189     68/push 0/imm32
 7190     89/<- %edx 4/r32/esp
 7191     (tailor-exit-descriptor %edx 0x10)
 7192     #
 7193     (write _test-input-stream "fn foo {\n")
 7194     (write _test-input-stream "  var a/eax: (addr array int) <- copy 0\n")
 7195     (write _test-input-stream "  var b: boolean\n")
 7196     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
 7197     (write _test-input-stream "}\n")
 7198     # convert
 7199     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7200     # registers except esp clobbered at this point
 7201     # restore ed
 7202     89/<- %edx 4/r32/esp
 7203     (flush _test-output-buffered-file)
 7204     (flush _test-error-buffered-file)
 7205 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7211     # check output
 7212     (check-stream-equal _test-output-stream  ""  "F - test-index-with-wrong-index-type: output should be empty")
 7213     (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")
 7214     # check that stop(1) was called
 7215     (check-ints-equal *(edx+4) 2 "F - test-index-with-wrong-index-type: exit status")
 7216     # don't restore from ebp
 7217     81 0/subop/add %esp 8/imm32
 7218     # . epilogue
 7219     5d/pop-to-ebp
 7220     c3/return
 7221 
 7222 test-index-with-offset-atom-index-type:
 7223     # . prologue
 7224     55/push-ebp
 7225     89/<- %ebp 4/r32/esp
 7226     # setup
 7227     (clear-stream _test-input-stream)
 7228     (clear-stream $_test-input-buffered-file->buffer)
 7229     (clear-stream _test-output-stream)
 7230     (clear-stream $_test-output-buffered-file->buffer)
 7231     (clear-stream _test-error-stream)
 7232     (clear-stream $_test-error-buffered-file->buffer)
 7233     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7234     68/push 0/imm32
 7235     68/push 0/imm32
 7236     89/<- %edx 4/r32/esp
 7237     (tailor-exit-descriptor %edx 0x10)
 7238     #
 7239     (write _test-input-stream "fn foo {\n")
 7240     (write _test-input-stream "  var a/eax: (addr array int) <- copy 0\n")
 7241     (write _test-input-stream "  var b: offset\n")
 7242     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
 7243     (write _test-input-stream "}\n")
 7244     # convert
 7245     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7246     # registers except esp clobbered at this point
 7247     # restore ed
 7248     89/<- %edx 4/r32/esp
 7249     (flush _test-output-buffered-file)
 7250     (flush _test-error-buffered-file)
 7251 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7257     # check output
 7258     (check-stream-equal _test-output-stream  ""  "F - test-index-with-offset-atom-index-type: output should be empty")
 7259     (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")
 7260     # check that stop(1) was called
 7261     (check-ints-equal *(edx+4) 2 "F - test-index-with-offset-atom-index-type: exit status")
 7262     # don't restore from ebp
 7263     81 0/subop/add %esp 8/imm32
 7264     # . epilogue
 7265     5d/pop-to-ebp
 7266     c3/return
 7267 
 7268 test-index-with-offset-on-stack:
 7269     # . prologue
 7270     55/push-ebp
 7271     89/<- %ebp 4/r32/esp
 7272     # setup
 7273     (clear-stream _test-input-stream)
 7274     (clear-stream $_test-input-buffered-file->buffer)
 7275     (clear-stream _test-output-stream)
 7276     (clear-stream $_test-output-buffered-file->buffer)
 7277     (clear-stream _test-error-stream)
 7278     (clear-stream $_test-error-buffered-file->buffer)
 7279     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7280     68/push 0/imm32
 7281     68/push 0/imm32
 7282     89/<- %edx 4/r32/esp
 7283     (tailor-exit-descriptor %edx 0x10)
 7284     #
 7285     (write _test-input-stream "fn foo {\n")
 7286     (write _test-input-stream "  var a/eax: (addr array int) <- copy 0\n")
 7287     (write _test-input-stream "  var b: int\n")
 7288     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
 7289     (write _test-input-stream "}\n")
 7290     # convert
 7291     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7292     # registers except esp clobbered at this point
 7293     # restore ed
 7294     89/<- %edx 4/r32/esp
 7295     (flush _test-output-buffered-file)
 7296     (flush _test-error-buffered-file)
 7297 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7303     # check output
 7304     (check-stream-equal _test-output-stream  ""  "F - test-index-with-offset-on-stack: output should be empty")
 7305     (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")
 7306     # check that stop(1) was called
 7307     (check-ints-equal *(edx+4) 2 "F - test-index-with-offset-on-stack: exit status")
 7308     # don't restore from ebp
 7309     81 0/subop/add %esp 8/imm32
 7310     # . epilogue
 7311     5d/pop-to-ebp
 7312     c3/return
 7313 
 7314 test-index-needs-offset-type:
 7315     # . prologue
 7316     55/push-ebp
 7317     89/<- %ebp 4/r32/esp
 7318     # setup
 7319     (clear-stream _test-input-stream)
 7320     (clear-stream $_test-input-buffered-file->buffer)
 7321     (clear-stream _test-output-stream)
 7322     (clear-stream $_test-output-buffered-file->buffer)
 7323     (clear-stream _test-error-stream)
 7324     (clear-stream $_test-error-buffered-file->buffer)
 7325     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7326     68/push 0/imm32
 7327     68/push 0/imm32
 7328     89/<- %edx 4/r32/esp
 7329     (tailor-exit-descriptor %edx 0x10)
 7330     #
 7331     (write _test-input-stream "fn foo {\n")
 7332     (write _test-input-stream "  var a/eax: (addr array t) <- copy 0\n")
 7333     (write _test-input-stream "  var b/ebx: int <- copy 0\n")
 7334     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
 7335     (write _test-input-stream "}\n")
 7336     (write _test-input-stream "type t {\n")  # size 12 is not a power of two
 7337     (write _test-input-stream "  x: int\n")
 7338     (write _test-input-stream "  y: int\n")
 7339     (write _test-input-stream "  z: int\n")
 7340     (write _test-input-stream "}\n")
 7341     # convert
 7342     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7343     # registers except esp clobbered at this point
 7344     # restore ed
 7345     89/<- %edx 4/r32/esp
 7346     (flush _test-output-buffered-file)
 7347     (flush _test-error-buffered-file)
 7348 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7354     # check output
 7355     (check-stream-equal _test-output-stream  ""  "F - test-index-needs-offset-type: output should be empty")
 7356     (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")
 7357     # check that stop(1) was called
 7358     (check-ints-equal *(edx+4) 2 "F - test-index-needs-offset-type: exit status")
 7359     # don't restore from ebp
 7360     81 0/subop/add %esp 8/imm32
 7361     # . epilogue
 7362     5d/pop-to-ebp
 7363     c3/return
 7364 
 7365 test-index-with-output-not-address:
 7366     # . prologue
 7367     55/push-ebp
 7368     89/<- %ebp 4/r32/esp
 7369     # setup
 7370     (clear-stream _test-input-stream)
 7371     (clear-stream $_test-input-buffered-file->buffer)
 7372     (clear-stream _test-output-stream)
 7373     (clear-stream $_test-output-buffered-file->buffer)
 7374     (clear-stream _test-error-stream)
 7375     (clear-stream $_test-error-buffered-file->buffer)
 7376     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7377     68/push 0/imm32
 7378     68/push 0/imm32
 7379     89/<- %edx 4/r32/esp
 7380     (tailor-exit-descriptor %edx 0x10)
 7381     #
 7382     (write _test-input-stream "fn foo {\n")
 7383     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
 7384     (write _test-input-stream "  var o/edi: int <- index a, 0\n")
 7385     (write _test-input-stream "}\n")
 7386     # convert
 7387     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7388     # registers except esp clobbered at this point
 7389     # restore ed
 7390     89/<- %edx 4/r32/esp
 7391     (flush _test-output-buffered-file)
 7392     (flush _test-error-buffered-file)
 7393 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7399     # check output
 7400     (check-stream-equal _test-output-stream  ""  "F - test-index-with-output-not-address: output should be empty")
 7401     (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")
 7402     # check that stop(1) was called
 7403     (check-ints-equal *(edx+4) 2 "F - test-index-with-output-not-address: exit status")
 7404     # don't restore from ebp
 7405     81 0/subop/add %esp 8/imm32
 7406     # . epilogue
 7407     5d/pop-to-ebp
 7408     c3/return
 7409 
 7410 test-index-with-output-not-address-2:
 7411     # . prologue
 7412     55/push-ebp
 7413     89/<- %ebp 4/r32/esp
 7414     # setup
 7415     (clear-stream _test-input-stream)
 7416     (clear-stream $_test-input-buffered-file->buffer)
 7417     (clear-stream _test-output-stream)
 7418     (clear-stream $_test-output-buffered-file->buffer)
 7419     (clear-stream _test-error-stream)
 7420     (clear-stream $_test-error-buffered-file->buffer)
 7421     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7422     68/push 0/imm32
 7423     68/push 0/imm32
 7424     89/<- %edx 4/r32/esp
 7425     (tailor-exit-descriptor %edx 0x10)
 7426     #
 7427     (write _test-input-stream "fn foo {\n")
 7428     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
 7429     (write _test-input-stream "  var o/edi: (int) <- index a, 0\n")
 7430     (write _test-input-stream "}\n")
 7431     # convert
 7432     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7433     # registers except esp clobbered at this point
 7434     # restore ed
 7435     89/<- %edx 4/r32/esp
 7436     (flush _test-output-buffered-file)
 7437     (flush _test-error-buffered-file)
 7438 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7444     # check output
 7445     (check-stream-equal _test-output-stream  ""  "F - test-index-with-output-not-address-2: output should be empty")
 7446     (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")
 7447     # check that stop(1) was called
 7448     (check-ints-equal *(edx+4) 2 "F - test-index-with-output-not-address-2: exit status")
 7449     # don't restore from ebp
 7450     81 0/subop/add %esp 8/imm32
 7451     # . epilogue
 7452     5d/pop-to-ebp
 7453     c3/return
 7454 
 7455 test-index-with-wrong-output-type:
 7456     # . prologue
 7457     55/push-ebp
 7458     89/<- %ebp 4/r32/esp
 7459     # setup
 7460     (clear-stream _test-input-stream)
 7461     (clear-stream $_test-input-buffered-file->buffer)
 7462     (clear-stream _test-output-stream)
 7463     (clear-stream $_test-output-buffered-file->buffer)
 7464     (clear-stream _test-error-stream)
 7465     (clear-stream $_test-error-buffered-file->buffer)
 7466     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7467     68/push 0/imm32
 7468     68/push 0/imm32
 7469     89/<- %edx 4/r32/esp
 7470     (tailor-exit-descriptor %edx 0x10)
 7471     #
 7472     (write _test-input-stream "fn foo {\n")
 7473     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
 7474     (write _test-input-stream "  var o/edi: (addr int) <- index a, 0\n")
 7475     (write _test-input-stream "}\n")
 7476     # convert
 7477     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7478     # registers except esp clobbered at this point
 7479     # restore ed
 7480     89/<- %edx 4/r32/esp
 7481     (flush _test-output-buffered-file)
 7482     (flush _test-error-buffered-file)
 7483 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7489     # check output
 7490     (check-stream-equal _test-output-stream  ""  "F - test-index-with-wrong-output-type: output should be empty")
 7491     (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")
 7492     # check that stop(1) was called
 7493     (check-ints-equal *(edx+4) 2 "F - test-index-with-wrong-output-type: exit status")
 7494     # don't restore from ebp
 7495     81 0/subop/add %esp 8/imm32
 7496     # . epilogue
 7497     5d/pop-to-ebp
 7498     c3/return
 7499 
 7500 test-index-with-wrong-output-compound-type:
 7501     # . prologue
 7502     55/push-ebp
 7503     89/<- %ebp 4/r32/esp
 7504     # setup
 7505     (clear-stream _test-input-stream)
 7506     (clear-stream $_test-input-buffered-file->buffer)
 7507     (clear-stream _test-output-stream)
 7508     (clear-stream $_test-output-buffered-file->buffer)
 7509     (clear-stream _test-error-stream)
 7510     (clear-stream $_test-error-buffered-file->buffer)
 7511     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7512     68/push 0/imm32
 7513     68/push 0/imm32
 7514     89/<- %edx 4/r32/esp
 7515     (tailor-exit-descriptor %edx 0x10)
 7516     #
 7517     (write _test-input-stream "fn foo {\n")
 7518     (write _test-input-stream "  var a/ebx: (addr array handle boolean) <- copy 0\n")
 7519     (write _test-input-stream "  var o/edi: (addr handle int) <- index a, 0\n")
 7520     (write _test-input-stream "}\n")
 7521     # convert
 7522     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7523     # registers except esp clobbered at this point
 7524     # restore ed
 7525     89/<- %edx 4/r32/esp
 7526     (flush _test-output-buffered-file)
 7527     (flush _test-error-buffered-file)
 7528 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7534     # check output
 7535     (check-stream-equal _test-output-stream  ""  "F - test-index-with-wrong-output-compound-type: output should be empty")
 7536     (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")
 7537     # check that stop(1) was called
 7538     (check-ints-equal *(edx+4) 2 "F - test-index-with-wrong-output-compound-type: exit status")
 7539     # don't restore from ebp
 7540     81 0/subop/add %esp 8/imm32
 7541     # . epilogue
 7542     5d/pop-to-ebp
 7543     c3/return
 7544 
 7545 test-index-with-no-inouts:
 7546     # . prologue
 7547     55/push-ebp
 7548     89/<- %ebp 4/r32/esp
 7549     # setup
 7550     (clear-stream _test-input-stream)
 7551     (clear-stream $_test-input-buffered-file->buffer)
 7552     (clear-stream _test-output-stream)
 7553     (clear-stream $_test-output-buffered-file->buffer)
 7554     (clear-stream _test-error-stream)
 7555     (clear-stream $_test-error-buffered-file->buffer)
 7556     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7557     68/push 0/imm32
 7558     68/push 0/imm32
 7559     89/<- %edx 4/r32/esp
 7560     (tailor-exit-descriptor %edx 0x10)
 7561     #
 7562     (write _test-input-stream "fn foo {\n")
 7563     (write _test-input-stream "  var c/ecx: (addr int) <- index\n")
 7564     (write _test-input-stream "}\n")
 7565     # convert
 7566     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7567     # registers except esp clobbered at this point
 7568     # restore ed
 7569     89/<- %edx 4/r32/esp
 7570     (flush _test-output-buffered-file)
 7571     (flush _test-error-buffered-file)
 7572 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7578     # check output
 7579     (check-stream-equal _test-output-stream  ""  "F - test-index-with-no-inouts: output should be empty")
 7580     (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")
 7581     # check that stop(1) was called
 7582     (check-ints-equal *(edx+4) 2 "F - test-index-with-no-inouts: exit status")
 7583     # don't restore from ebp
 7584     81 0/subop/add %esp 8/imm32
 7585     # . epilogue
 7586     5d/pop-to-ebp
 7587     c3/return
 7588 
 7589 test-index-with-too-few-inouts:
 7590     # . prologue
 7591     55/push-ebp
 7592     89/<- %ebp 4/r32/esp
 7593     # setup
 7594     (clear-stream _test-input-stream)
 7595     (clear-stream $_test-input-buffered-file->buffer)
 7596     (clear-stream _test-output-stream)
 7597     (clear-stream $_test-output-buffered-file->buffer)
 7598     (clear-stream _test-error-stream)
 7599     (clear-stream $_test-error-buffered-file->buffer)
 7600     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7601     68/push 0/imm32
 7602     68/push 0/imm32
 7603     89/<- %edx 4/r32/esp
 7604     (tailor-exit-descriptor %edx 0x10)
 7605     #
 7606     (write _test-input-stream "fn foo {\n")
 7607     (write _test-input-stream "  var a: (array int 3)\n")
 7608     (write _test-input-stream "  var c/ecx: (addr int) <- index a\n")
 7609     (write _test-input-stream "}\n")
 7610     # convert
 7611     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7612     # registers except esp clobbered at this point
 7613     # restore ed
 7614     89/<- %edx 4/r32/esp
 7615     (flush _test-output-buffered-file)
 7616     (flush _test-error-buffered-file)
 7617 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7623     # check output
 7624     (check-stream-equal _test-output-stream  ""  "F - test-index-with-too-few-inouts: output should be empty")
 7625     (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")
 7626     # check that stop(1) was called
 7627     (check-ints-equal *(edx+4) 2 "F - test-index-with-too-few-inouts: exit status")
 7628     # don't restore from ebp
 7629     81 0/subop/add %esp 8/imm32
 7630     # . epilogue
 7631     5d/pop-to-ebp
 7632     c3/return
 7633 
 7634 test-index-with-too-many-inouts:
 7635     # . prologue
 7636     55/push-ebp
 7637     89/<- %ebp 4/r32/esp
 7638     # setup
 7639     (clear-stream _test-input-stream)
 7640     (clear-stream $_test-input-buffered-file->buffer)
 7641     (clear-stream _test-output-stream)
 7642     (clear-stream $_test-output-buffered-file->buffer)
 7643     (clear-stream _test-error-stream)
 7644     (clear-stream $_test-error-buffered-file->buffer)
 7645     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7646     68/push 0/imm32
 7647     68/push 0/imm32
 7648     89/<- %edx 4/r32/esp
 7649     (tailor-exit-descriptor %edx 0x10)
 7650     #
 7651     (write _test-input-stream "fn foo {\n")
 7652     (write _test-input-stream "  var a: (array int 3)\n")
 7653     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0, 0\n")
 7654     (write _test-input-stream "}\n")
 7655     # convert
 7656     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7657     # registers except esp clobbered at this point
 7658     # restore ed
 7659     89/<- %edx 4/r32/esp
 7660     (flush _test-output-buffered-file)
 7661     (flush _test-error-buffered-file)
 7662 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7668     # check output
 7669     (check-stream-equal _test-output-stream  ""  "F - test-index-with-too-many-inouts: output should be empty")
 7670     (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")
 7671     # check that stop(1) was called
 7672     (check-ints-equal *(edx+4) 2 "F - test-index-with-too-many-inouts: exit status")
 7673     # don't restore from ebp
 7674     81 0/subop/add %esp 8/imm32
 7675     # . epilogue
 7676     5d/pop-to-ebp
 7677     c3/return
 7678 
 7679 test-index-with-no-output:
 7680     # . prologue
 7681     55/push-ebp
 7682     89/<- %ebp 4/r32/esp
 7683     # setup
 7684     (clear-stream _test-input-stream)
 7685     (clear-stream $_test-input-buffered-file->buffer)
 7686     (clear-stream _test-output-stream)
 7687     (clear-stream $_test-output-buffered-file->buffer)
 7688     (clear-stream _test-error-stream)
 7689     (clear-stream $_test-error-buffered-file->buffer)
 7690     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7691     68/push 0/imm32
 7692     68/push 0/imm32
 7693     89/<- %edx 4/r32/esp
 7694     (tailor-exit-descriptor %edx 0x10)
 7695     #
 7696     (write _test-input-stream "fn foo {\n")
 7697     (write _test-input-stream "  var a: (array int 3)\n")
 7698     (write _test-input-stream "  index a, 0\n")
 7699     (write _test-input-stream "}\n")
 7700     # convert
 7701     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7702     # registers except esp clobbered at this point
 7703     # restore ed
 7704     89/<- %edx 4/r32/esp
 7705     (flush _test-output-buffered-file)
 7706     (flush _test-error-buffered-file)
 7707 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7713     # check output
 7714     (check-stream-equal _test-output-stream  ""  "F - test-index-with-no-output: output should be empty")
 7715     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: must have an output"  "F - test-index-with-no-output: error message")
 7716     # check that stop(1) was called
 7717     (check-ints-equal *(edx+4) 2 "F - test-index-with-no-output: exit status")
 7718     # don't restore from ebp
 7719     81 0/subop/add %esp 8/imm32
 7720     # . epilogue
 7721     5d/pop-to-ebp
 7722     c3/return
 7723 
 7724 test-index-with-too-many-outputs:
 7725     # . prologue
 7726     55/push-ebp
 7727     89/<- %ebp 4/r32/esp
 7728     # setup
 7729     (clear-stream _test-input-stream)
 7730     (clear-stream $_test-input-buffered-file->buffer)
 7731     (clear-stream _test-output-stream)
 7732     (clear-stream $_test-output-buffered-file->buffer)
 7733     (clear-stream _test-error-stream)
 7734     (clear-stream $_test-error-buffered-file->buffer)
 7735     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7736     68/push 0/imm32
 7737     68/push 0/imm32
 7738     89/<- %edx 4/r32/esp
 7739     (tailor-exit-descriptor %edx 0x10)
 7740     #
 7741     (write _test-input-stream "fn foo {\n")
 7742     (write _test-input-stream "  var a: (array int 3)\n")
 7743     (write _test-input-stream "  var b/eax: (addr int) <- copy 0\n")
 7744     (write _test-input-stream "  var c/ecx: (addr int) <- copy 0\n")
 7745     (write _test-input-stream "  b, c <- index a, 0\n")
 7746     (write _test-input-stream "}\n")
 7747     # convert
 7748     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7749     # registers except esp clobbered at this point
 7750     # restore ed
 7751     89/<- %edx 4/r32/esp
 7752     (flush _test-output-buffered-file)
 7753     (flush _test-error-buffered-file)
 7754 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7760     # check output
 7761     (check-stream-equal _test-output-stream  ""  "F - test-index-with-too-many-outputs: output should be empty")
 7762     (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")
 7763     # check that stop(1) was called
 7764     (check-ints-equal *(edx+4) 2 "F - test-index-with-too-many-outputs: exit status")
 7765     # don't restore from ebp
 7766     81 0/subop/add %esp 8/imm32
 7767     # . epilogue
 7768     5d/pop-to-ebp
 7769     c3/return
 7770 
 7771 test-compute-offset-with-non-array-atom-base-type:
 7772     # . prologue
 7773     55/push-ebp
 7774     89/<- %ebp 4/r32/esp
 7775     # setup
 7776     (clear-stream _test-input-stream)
 7777     (clear-stream $_test-input-buffered-file->buffer)
 7778     (clear-stream _test-output-stream)
 7779     (clear-stream $_test-output-buffered-file->buffer)
 7780     (clear-stream _test-error-stream)
 7781     (clear-stream $_test-error-buffered-file->buffer)
 7782     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7783     68/push 0/imm32
 7784     68/push 0/imm32
 7785     89/<- %edx 4/r32/esp
 7786     (tailor-exit-descriptor %edx 0x10)
 7787     #
 7788     (write _test-input-stream "fn foo {\n")
 7789     (write _test-input-stream "  var a: int\n")
 7790     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0\n")
 7791     (write _test-input-stream "}\n")
 7792     # convert
 7793     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7794     # registers except esp clobbered at this point
 7795     # restore ed
 7796     89/<- %edx 4/r32/esp
 7797     (flush _test-output-buffered-file)
 7798     (flush _test-error-buffered-file)
 7799 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7805     # check output
 7806     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-non-array-atom-base-type: output should be empty")
 7807     (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")
 7808     # check that stop(1) was called
 7809     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-non-array-atom-base-type: exit status")
 7810     # don't restore from ebp
 7811     81 0/subop/add %esp 8/imm32
 7812     # . epilogue
 7813     5d/pop-to-ebp
 7814     c3/return
 7815 
 7816 test-compute-offset-with-non-array-compound-base-type:
 7817     # . prologue
 7818     55/push-ebp
 7819     89/<- %ebp 4/r32/esp
 7820     # setup
 7821     (clear-stream _test-input-stream)
 7822     (clear-stream $_test-input-buffered-file->buffer)
 7823     (clear-stream _test-output-stream)
 7824     (clear-stream $_test-output-buffered-file->buffer)
 7825     (clear-stream _test-error-stream)
 7826     (clear-stream $_test-error-buffered-file->buffer)
 7827     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7828     68/push 0/imm32
 7829     68/push 0/imm32
 7830     89/<- %edx 4/r32/esp
 7831     (tailor-exit-descriptor %edx 0x10)
 7832     #
 7833     (write _test-input-stream "fn foo {\n")
 7834     (write _test-input-stream "  var a: (handle int)\n")
 7835     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0\n")
 7836     (write _test-input-stream "}\n")
 7837     # convert
 7838     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7839     # registers except esp clobbered at this point
 7840     # restore ed
 7841     89/<- %edx 4/r32/esp
 7842     (flush _test-output-buffered-file)
 7843     (flush _test-error-buffered-file)
 7844 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7850     # check output
 7851     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-non-array-compound-base-type: output should be empty")
 7852     (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")
 7853     # check that stop(1) was called
 7854     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-non-array-compound-base-type: exit status")
 7855     # don't restore from ebp
 7856     81 0/subop/add %esp 8/imm32
 7857     # . epilogue
 7858     5d/pop-to-ebp
 7859     c3/return
 7860 
 7861 test-compute-offset-with-non-array-compound-base-type-2:
 7862     # . prologue
 7863     55/push-ebp
 7864     89/<- %ebp 4/r32/esp
 7865     # setup
 7866     (clear-stream _test-input-stream)
 7867     (clear-stream $_test-input-buffered-file->buffer)
 7868     (clear-stream _test-output-stream)
 7869     (clear-stream $_test-output-buffered-file->buffer)
 7870     (clear-stream _test-error-stream)
 7871     (clear-stream $_test-error-buffered-file->buffer)
 7872     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7873     68/push 0/imm32
 7874     68/push 0/imm32
 7875     89/<- %edx 4/r32/esp
 7876     (tailor-exit-descriptor %edx 0x10)
 7877     #
 7878     (write _test-input-stream "fn foo {\n")
 7879     (write _test-input-stream "  var a: (addr int)\n")
 7880     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0\n")
 7881     (write _test-input-stream "}\n")
 7882     # convert
 7883     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7884     # registers except esp clobbered at this point
 7885     # restore ed
 7886     89/<- %edx 4/r32/esp
 7887     (flush _test-output-buffered-file)
 7888     (flush _test-error-buffered-file)
 7889 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7895     # check output
 7896     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-non-array-compound-base-type-2: output should be empty")
 7897     (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")
 7898     # check that stop(1) was called
 7899     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-non-array-compound-base-type-2: exit status")
 7900     # don't restore from ebp
 7901     81 0/subop/add %esp 8/imm32
 7902     # . epilogue
 7903     5d/pop-to-ebp
 7904     c3/return
 7905 
 7906 test-compute-offset-with-array-atom-base-type:
 7907     # . prologue
 7908     55/push-ebp
 7909     89/<- %ebp 4/r32/esp
 7910     # setup
 7911     (clear-stream _test-input-stream)
 7912     (clear-stream $_test-input-buffered-file->buffer)
 7913     (clear-stream _test-output-stream)
 7914     (clear-stream $_test-output-buffered-file->buffer)
 7915     (clear-stream _test-error-stream)
 7916     (clear-stream $_test-error-buffered-file->buffer)
 7917     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7918     68/push 0/imm32
 7919     68/push 0/imm32
 7920     89/<- %edx 4/r32/esp
 7921     (tailor-exit-descriptor %edx 0x10)
 7922     #
 7923     (write _test-input-stream "fn foo {\n")
 7924     (write _test-input-stream "  var a: array\n")
 7925     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0\n")
 7926     (write _test-input-stream "}\n")
 7927     # convert
 7928     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7929     # registers except esp clobbered at this point
 7930     # restore ed
 7931     89/<- %edx 4/r32/esp
 7932     (flush _test-output-buffered-file)
 7933     (flush _test-error-buffered-file)
 7934 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7940     # check output
 7941     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-array-atom-base-type: output should be empty")
 7942     (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")
 7943     # check that stop(1) was called
 7944     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-array-atom-base-type: exit status")
 7945     # don't restore from ebp
 7946     81 0/subop/add %esp 8/imm32
 7947     # . epilogue
 7948     5d/pop-to-ebp
 7949     c3/return
 7950 
 7951 test-compute-offset-with-wrong-index-type:
 7952     # . prologue
 7953     55/push-ebp
 7954     89/<- %ebp 4/r32/esp
 7955     # setup
 7956     (clear-stream _test-input-stream)
 7957     (clear-stream $_test-input-buffered-file->buffer)
 7958     (clear-stream _test-output-stream)
 7959     (clear-stream $_test-output-buffered-file->buffer)
 7960     (clear-stream _test-error-stream)
 7961     (clear-stream $_test-error-buffered-file->buffer)
 7962     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7963     68/push 0/imm32
 7964     68/push 0/imm32
 7965     89/<- %edx 4/r32/esp
 7966     (tailor-exit-descriptor %edx 0x10)
 7967     #
 7968     (write _test-input-stream "fn foo {\n")
 7969     (write _test-input-stream "  var a/eax: (addr array int) <- copy 0\n")
 7970     (write _test-input-stream "  var b: boolean\n")
 7971     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, b\n")
 7972     (write _test-input-stream "}\n")
 7973     # convert
 7974     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7975     # registers except esp clobbered at this point
 7976     # restore ed
 7977     89/<- %edx 4/r32/esp
 7978     (flush _test-output-buffered-file)
 7979     (flush _test-error-buffered-file)
 7980 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7986     # check output
 7987     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-wrong-index-type: output should be empty")
 7988     (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")
 7989     # check that stop(1) was called
 7990     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-wrong-index-type: exit status")
 7991     # don't restore from ebp
 7992     81 0/subop/add %esp 8/imm32
 7993     # . epilogue
 7994     5d/pop-to-ebp
 7995     c3/return
 7996 
 7997 test-compute-offset-with-output-not-offset:
 7998     # . prologue
 7999     55/push-ebp
 8000     89/<- %ebp 4/r32/esp
 8001     # setup
 8002     (clear-stream _test-input-stream)
 8003     (clear-stream $_test-input-buffered-file->buffer)
 8004     (clear-stream _test-output-stream)
 8005     (clear-stream $_test-output-buffered-file->buffer)
 8006     (clear-stream _test-error-stream)
 8007     (clear-stream $_test-error-buffered-file->buffer)
 8008     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8009     68/push 0/imm32
 8010     68/push 0/imm32
 8011     89/<- %edx 4/r32/esp
 8012     (tailor-exit-descriptor %edx 0x10)
 8013     #
 8014     (write _test-input-stream "fn foo {\n")
 8015     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
 8016     (write _test-input-stream "  var o/edi: int <- compute-offset a, 0\n")
 8017     (write _test-input-stream "}\n")
 8018     # convert
 8019     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8020     # registers except esp clobbered at this point
 8021     # restore ed
 8022     89/<- %edx 4/r32/esp
 8023     (flush _test-output-buffered-file)
 8024     (flush _test-error-buffered-file)
 8025 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8031     # check output
 8032     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-output-not-offset: output should be empty")
 8033     (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")
 8034     # check that stop(1) was called
 8035     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-output-not-offset: exit status")
 8036     # don't restore from ebp
 8037     81 0/subop/add %esp 8/imm32
 8038     # . epilogue
 8039     5d/pop-to-ebp
 8040     c3/return
 8041 
 8042 test-compute-offset-with-output-not-address-2:
 8043     # . prologue
 8044     55/push-ebp
 8045     89/<- %ebp 4/r32/esp
 8046     # setup
 8047     (clear-stream _test-input-stream)
 8048     (clear-stream $_test-input-buffered-file->buffer)
 8049     (clear-stream _test-output-stream)
 8050     (clear-stream $_test-output-buffered-file->buffer)
 8051     (clear-stream _test-error-stream)
 8052     (clear-stream $_test-error-buffered-file->buffer)
 8053     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8054     68/push 0/imm32
 8055     68/push 0/imm32
 8056     89/<- %edx 4/r32/esp
 8057     (tailor-exit-descriptor %edx 0x10)
 8058     #
 8059     (write _test-input-stream "fn foo {\n")
 8060     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
 8061     (write _test-input-stream "  var o/edi: (int) <- compute-offset a, 0\n")
 8062     (write _test-input-stream "}\n")
 8063     # convert
 8064     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8065     # registers except esp clobbered at this point
 8066     # restore ed
 8067     89/<- %edx 4/r32/esp
 8068     (flush _test-output-buffered-file)
 8069     (flush _test-error-buffered-file)
 8070 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8076     # check output
 8077     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-output-not-address-2: output should be empty")
 8078     (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")
 8079     # check that stop(1) was called
 8080     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-output-not-address-2: exit status")
 8081     # don't restore from ebp
 8082     81 0/subop/add %esp 8/imm32
 8083     # . epilogue
 8084     5d/pop-to-ebp
 8085     c3/return
 8086 
 8087 test-compute-offset-with-wrong-output-type:
 8088     # . prologue
 8089     55/push-ebp
 8090     89/<- %ebp 4/r32/esp
 8091     # setup
 8092     (clear-stream _test-input-stream)
 8093     (clear-stream $_test-input-buffered-file->buffer)
 8094     (clear-stream _test-output-stream)
 8095     (clear-stream $_test-output-buffered-file->buffer)
 8096     (clear-stream _test-error-stream)
 8097     (clear-stream $_test-error-buffered-file->buffer)
 8098     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8099     68/push 0/imm32
 8100     68/push 0/imm32
 8101     89/<- %edx 4/r32/esp
 8102     (tailor-exit-descriptor %edx 0x10)
 8103     #
 8104     (write _test-input-stream "fn foo {\n")
 8105     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
 8106     (write _test-input-stream "  var o/edi: (offset int) <- compute-offset a, 0\n")
 8107     (write _test-input-stream "}\n")
 8108     # convert
 8109     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8110     # registers except esp clobbered at this point
 8111     # restore ed
 8112     89/<- %edx 4/r32/esp
 8113     (flush _test-output-buffered-file)
 8114     (flush _test-error-buffered-file)
 8115 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8121     # check output
 8122     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-wrong-output-type: output should be empty")
 8123     (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")
 8124     # check that stop(1) was called
 8125     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-wrong-output-type: exit status")
 8126     # don't restore from ebp
 8127     81 0/subop/add %esp 8/imm32
 8128     # . epilogue
 8129     5d/pop-to-ebp
 8130     c3/return
 8131 
 8132 test-compute-offset-with-wrong-output-compound-type:
 8133     # . prologue
 8134     55/push-ebp
 8135     89/<- %ebp 4/r32/esp
 8136     # setup
 8137     (clear-stream _test-input-stream)
 8138     (clear-stream $_test-input-buffered-file->buffer)
 8139     (clear-stream _test-output-stream)
 8140     (clear-stream $_test-output-buffered-file->buffer)
 8141     (clear-stream _test-error-stream)
 8142     (clear-stream $_test-error-buffered-file->buffer)
 8143     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8144     68/push 0/imm32
 8145     68/push 0/imm32
 8146     89/<- %edx 4/r32/esp
 8147     (tailor-exit-descriptor %edx 0x10)
 8148     #
 8149     (write _test-input-stream "fn foo {\n")
 8150     (write _test-input-stream "  var a/ebx: (addr array handle boolean) <- copy 0\n")
 8151     (write _test-input-stream "  var o/edi: (offset handle int) <- compute-offset a, 0\n")
 8152     (write _test-input-stream "}\n")
 8153     # convert
 8154     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8155     # registers except esp clobbered at this point
 8156     # restore ed
 8157     89/<- %edx 4/r32/esp
 8158     (flush _test-output-buffered-file)
 8159     (flush _test-error-buffered-file)
 8160 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8166     # check output
 8167     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-wrong-output-compound-type: output should be empty")
 8168     (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")
 8169     # check that stop(1) was called
 8170     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-wrong-output-compound-type: exit status")
 8171     # don't restore from ebp
 8172     81 0/subop/add %esp 8/imm32
 8173     # . epilogue
 8174     5d/pop-to-ebp
 8175     c3/return
 8176 
 8177 test-compute-offset-with-no-inouts:
 8178     # . prologue
 8179     55/push-ebp
 8180     89/<- %ebp 4/r32/esp
 8181     # setup
 8182     (clear-stream _test-input-stream)
 8183     (clear-stream $_test-input-buffered-file->buffer)
 8184     (clear-stream _test-output-stream)
 8185     (clear-stream $_test-output-buffered-file->buffer)
 8186     (clear-stream _test-error-stream)
 8187     (clear-stream $_test-error-buffered-file->buffer)
 8188     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8189     68/push 0/imm32
 8190     68/push 0/imm32
 8191     89/<- %edx 4/r32/esp
 8192     (tailor-exit-descriptor %edx 0x10)
 8193     #
 8194     (write _test-input-stream "fn foo {\n")
 8195     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset\n")
 8196     (write _test-input-stream "}\n")
 8197     # convert
 8198     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8199     # registers except esp clobbered at this point
 8200     # restore ed
 8201     89/<- %edx 4/r32/esp
 8202     (flush _test-output-buffered-file)
 8203     (flush _test-error-buffered-file)
 8204 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8210     # check output
 8211     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-no-inouts: output should be empty")
 8212     (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")
 8213     # check that stop(1) was called
 8214     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-no-inouts: exit status")
 8215     # don't restore from ebp
 8216     81 0/subop/add %esp 8/imm32
 8217     # . epilogue
 8218     5d/pop-to-ebp
 8219     c3/return
 8220 
 8221 test-compute-offset-with-too-few-inouts:
 8222     # . prologue
 8223     55/push-ebp
 8224     89/<- %ebp 4/r32/esp
 8225     # setup
 8226     (clear-stream _test-input-stream)
 8227     (clear-stream $_test-input-buffered-file->buffer)
 8228     (clear-stream _test-output-stream)
 8229     (clear-stream $_test-output-buffered-file->buffer)
 8230     (clear-stream _test-error-stream)
 8231     (clear-stream $_test-error-buffered-file->buffer)
 8232     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8233     68/push 0/imm32
 8234     68/push 0/imm32
 8235     89/<- %edx 4/r32/esp
 8236     (tailor-exit-descriptor %edx 0x10)
 8237     #
 8238     (write _test-input-stream "fn foo {\n")
 8239     (write _test-input-stream "  var a: (array int 3)\n")
 8240     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a\n")
 8241     (write _test-input-stream "}\n")
 8242     # convert
 8243     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8244     # registers except esp clobbered at this point
 8245     # restore ed
 8246     89/<- %edx 4/r32/esp
 8247     (flush _test-output-buffered-file)
 8248     (flush _test-error-buffered-file)
 8249 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8255     # check output
 8256     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-too-few-inouts: output should be empty")
 8257     (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")
 8258     # check that stop(1) was called
 8259     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-too-few-inouts: exit status")
 8260     # don't restore from ebp
 8261     81 0/subop/add %esp 8/imm32
 8262     # . epilogue
 8263     5d/pop-to-ebp
 8264     c3/return
 8265 
 8266 test-compute-offset-with-too-many-inouts:
 8267     # . prologue
 8268     55/push-ebp
 8269     89/<- %ebp 4/r32/esp
 8270     # setup
 8271     (clear-stream _test-input-stream)
 8272     (clear-stream $_test-input-buffered-file->buffer)
 8273     (clear-stream _test-output-stream)
 8274     (clear-stream $_test-output-buffered-file->buffer)
 8275     (clear-stream _test-error-stream)
 8276     (clear-stream $_test-error-buffered-file->buffer)
 8277     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8278     68/push 0/imm32
 8279     68/push 0/imm32
 8280     89/<- %edx 4/r32/esp
 8281     (tailor-exit-descriptor %edx 0x10)
 8282     #
 8283     (write _test-input-stream "fn foo {\n")
 8284     (write _test-input-stream "  var a: (array int 3)\n")
 8285     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0, 0\n")
 8286     (write _test-input-stream "}\n")
 8287     # convert
 8288     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8289     # registers except esp clobbered at this point
 8290     # restore ed
 8291     89/<- %edx 4/r32/esp
 8292     (flush _test-output-buffered-file)
 8293     (flush _test-error-buffered-file)
 8294 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8300     # check output
 8301     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-too-many-inouts: output should be empty")
 8302     (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")
 8303     # check that stop(1) was called
 8304     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-too-many-inouts: exit status")
 8305     # don't restore from ebp
 8306     81 0/subop/add %esp 8/imm32
 8307     # . epilogue
 8308     5d/pop-to-ebp
 8309     c3/return
 8310 
 8311 test-compute-offset-with-no-output:
 8312     # . prologue
 8313     55/push-ebp
 8314     89/<- %ebp 4/r32/esp
 8315     # setup
 8316     (clear-stream _test-input-stream)
 8317     (clear-stream $_test-input-buffered-file->buffer)
 8318     (clear-stream _test-output-stream)
 8319     (clear-stream $_test-output-buffered-file->buffer)
 8320     (clear-stream _test-error-stream)
 8321     (clear-stream $_test-error-buffered-file->buffer)
 8322     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8323     68/push 0/imm32
 8324     68/push 0/imm32
 8325     89/<- %edx 4/r32/esp
 8326     (tailor-exit-descriptor %edx 0x10)
 8327     #
 8328     (write _test-input-stream "fn foo {\n")
 8329     (write _test-input-stream "  var a: (array int 3)\n")
 8330     (write _test-input-stream "  compute-offset a, 0\n")
 8331     (write _test-input-stream "}\n")
 8332     # convert
 8333     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8334     # registers except esp clobbered at this point
 8335     # restore ed
 8336     89/<- %edx 4/r32/esp
 8337     (flush _test-output-buffered-file)
 8338     (flush _test-error-buffered-file)
 8339 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8345     # check output
 8346     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-no-output: output should be empty")
 8347     (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")
 8348     # check that stop(1) was called
 8349     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-no-output: exit status")
 8350     # don't restore from ebp
 8351     81 0/subop/add %esp 8/imm32
 8352     # . epilogue
 8353     5d/pop-to-ebp
 8354     c3/return
 8355 
 8356 test-compute-offset-with-too-many-outputs:
 8357     # . prologue
 8358     55/push-ebp
 8359     89/<- %ebp 4/r32/esp
 8360     # setup
 8361     (clear-stream _test-input-stream)
 8362     (clear-stream $_test-input-buffered-file->buffer)
 8363     (clear-stream _test-output-stream)
 8364     (clear-stream $_test-output-buffered-file->buffer)
 8365     (clear-stream _test-error-stream)
 8366     (clear-stream $_test-error-buffered-file->buffer)
 8367     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8368     68/push 0/imm32
 8369     68/push 0/imm32
 8370     89/<- %edx 4/r32/esp
 8371     (tailor-exit-descriptor %edx 0x10)
 8372     #
 8373     (write _test-input-stream "fn foo {\n")
 8374     (write _test-input-stream "  var a: (array int 3)\n")
 8375     (write _test-input-stream "  var b/eax: (offset int) <- copy 0\n")
 8376     (write _test-input-stream "  var c/ecx: (addr int) <- copy 0\n")
 8377     (write _test-input-stream "  b, c <- compute-offset a, 0\n")
 8378     (write _test-input-stream "}\n")
 8379     # convert
 8380     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8381     # registers except esp clobbered at this point
 8382     # restore ed
 8383     89/<- %edx 4/r32/esp
 8384     (flush _test-output-buffered-file)
 8385     (flush _test-error-buffered-file)
 8386 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8392     # check output
 8393     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-too-many-outputs: output should be empty")
 8394     (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")
 8395     # check that stop(1) was called
 8396     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-too-many-outputs: exit status")
 8397     # don't restore from ebp
 8398     81 0/subop/add %esp 8/imm32
 8399     # . epilogue
 8400     5d/pop-to-ebp
 8401     c3/return
 8402 
 8403 test-convert-read-from-stream:
 8404     # . prologue
 8405     55/push-ebp
 8406     89/<- %ebp 4/r32/esp
 8407     # setup
 8408     (clear-stream _test-input-stream)
 8409     (clear-stream $_test-input-buffered-file->buffer)
 8410     (clear-stream _test-output-stream)
 8411     (clear-stream $_test-output-buffered-file->buffer)
 8412     #
 8413     (write _test-input-stream "fn foo {\n")
 8414     (write _test-input-stream "  var s/esi: (addr stream int) <- copy 0\n")
 8415     (write _test-input-stream "  var o/ecx: (addr int) <- copy 0\n")
 8416     (write _test-input-stream "  read-from-stream s, o\n")
 8417     (write _test-input-stream "}\n")
 8418     # convert
 8419     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 8420     # registers except esp clobbered at this point
 8421     # restore ed
 8422     89/<- %edx 4/r32/esp
 8423     (flush _test-output-buffered-file)
 8424     (flush _test-error-buffered-file)
 8425 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8431     # check output
 8432     (check-next-stream-line-equal _test-output-stream "foo:"                            "F - test-convert-read-from-stream/0")
 8433     (check-next-stream-line-equal _test-output-stream "  # . prologue"                  "F - test-convert-read-from-stream/1")
 8434     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                   "F - test-convert-read-from-stream/2")
 8435     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"          "F - test-convert-read-from-stream/3")
 8436     (check-next-stream-line-equal _test-output-stream "  {"                             "F - test-convert-read-from-stream/4")
 8437     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"           "F - test-convert-read-from-stream/5")
 8438     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %esi"        "F - test-convert-read-from-stream/6")
 8439     (check-next-stream-line-equal _test-output-stream "    be/copy-to-esi 0/imm32"      "F - test-convert-read-from-stream/7")
 8440     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"        "F - test-convert-read-from-stream/8")
 8441     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"      "F - test-convert-read-from-stream/9")
 8442     (check-next-stream-line-equal _test-output-stream "    (read-from-stream %esi %ecx 0x00000004)"  "F - test-convert-read-from-stream/10")
 8443     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-read-from-stream/11")
 8444     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %esi"         "F - test-convert-read-from-stream/12")
 8445     (check-next-stream-line-equal _test-output-stream "  }"                             "F - test-convert-read-from-stream/13")
 8446     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"          "F - test-convert-read-from-stream/14")
 8447     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                  "F - test-convert-read-from-stream/15")
 8448     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"          "F - test-convert-read-from-stream/16")
 8449     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                 "F - test-convert-read-from-stream/17")
 8450     (check-next-stream-line-equal _test-output-stream "  c3/return"                     "F - test-convert-read-from-stream/18")
 8451     # . epilogue
 8452     89/<- %esp 5/r32/ebp
 8453     5d/pop-to-ebp
 8454     c3/return
 8455 
 8456 test-convert-read-from-stream-with-correct-payload-size:
 8457     # . prologue
 8458     55/push-ebp
 8459     89/<- %ebp 4/r32/esp
 8460     # setup
 8461     (clear-stream _test-input-stream)
 8462     (clear-stream $_test-input-buffered-file->buffer)
 8463     (clear-stream _test-output-stream)
 8464     (clear-stream $_test-output-buffered-file->buffer)
 8465     #
 8466     (write _test-input-stream "fn foo {\n")
 8467     (write _test-input-stream "  var s/esi: (addr stream handle int) <- copy 0\n")
 8468     (write _test-input-stream "  var o/ecx: (addr handle int) <- copy 0\n")
 8469     (write _test-input-stream "  read-from-stream s, o\n")
 8470     (write _test-input-stream "}\n")
 8471     # convert
 8472     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 8473     # registers except esp clobbered at this point
 8474     # restore ed
 8475     89/<- %edx 4/r32/esp
 8476     (flush _test-output-buffered-file)
 8477     (flush _test-error-buffered-file)
 8478 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8484     # check output
 8485     (check-next-stream-line-equal _test-output-stream "foo:"                            "F - test-convert-read-from-stream-with-correct-payload-size/0")
 8486     (check-next-stream-line-equal _test-output-stream "  # . prologue"                  "F - test-convert-read-from-stream-with-correct-payload-size/1")
 8487     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                   "F - test-convert-read-from-stream-with-correct-payload-size/2")
 8488     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"          "F - test-convert-read-from-stream-with-correct-payload-size/3")
 8489     (check-next-stream-line-equal _test-output-stream "  {"                             "F - test-convert-read-from-stream-with-correct-payload-size/4")
 8490     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"           "F - test-convert-read-from-stream-with-correct-payload-size/5")
 8491     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %esi"        "F - test-convert-read-from-stream-with-correct-payload-size/6")
 8492     (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")
 8493     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"        "F - test-convert-read-from-stream-with-correct-payload-size/8")
 8494     (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")
 8495     (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")
 8496     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-read-from-stream-with-correct-payload-size/11")
 8497     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %esi"         "F - test-convert-read-from-stream-with-correct-payload-size/12")
 8498     (check-next-stream-line-equal _test-output-stream "  }"                             "F - test-convert-read-from-stream-with-correct-payload-size/13")
 8499     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"          "F - test-convert-read-from-stream-with-correct-payload-size/14")
 8500     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                  "F - test-convert-read-from-stream-with-correct-payload-size/15")
 8501     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"          "F - test-convert-read-from-stream-with-correct-payload-size/16")
 8502     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                 "F - test-convert-read-from-stream-with-correct-payload-size/17")
 8503     (check-next-stream-line-equal _test-output-stream "  c3/return"                     "F - test-convert-read-from-stream-with-correct-payload-size/18")
 8504     # . epilogue
 8505     89/<- %esp 5/r32/ebp
 8506     5d/pop-to-ebp
 8507     c3/return
 8508 
 8509 test-read-from-stream-with-non-stream-atom-base-type:
 8510     # . prologue
 8511     55/push-ebp
 8512     89/<- %ebp 4/r32/esp
 8513     # setup
 8514     (clear-stream _test-input-stream)
 8515     (clear-stream $_test-input-buffered-file->buffer)
 8516     (clear-stream _test-output-stream)
 8517     (clear-stream $_test-output-buffered-file->buffer)
 8518     (clear-stream _test-error-stream)
 8519     (clear-stream $_test-error-buffered-file->buffer)
 8520     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8521     68/push 0/imm32
 8522     68/push 0/imm32
 8523     89/<- %edx 4/r32/esp
 8524     (tailor-exit-descriptor %edx 0x10)
 8525     #
 8526     (write _test-input-stream "fn foo {\n")
 8527     (write _test-input-stream "  var a: int\n")
 8528     (write _test-input-stream "  read-from-stream a, 0\n")
 8529     (write _test-input-stream "}\n")
 8530     # convert
 8531     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8532     # registers except esp clobbered at this point
 8533     # restore ed
 8534     89/<- %edx 4/r32/esp
 8535     (flush _test-output-buffered-file)
 8536     (flush _test-error-buffered-file)
 8537 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8543     # check output
 8544     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-non-stream-atom-base-type: output should be empty")
 8545     (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")
 8546     # check that stop(1) was called
 8547     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-non-stream-atom-base-type: exit status")
 8548     # don't restore from ebp
 8549     81 0/subop/add %esp 8/imm32
 8550     # . epilogue
 8551     5d/pop-to-ebp
 8552     c3/return
 8553 
 8554 test-read-from-stream-with-non-stream-compound-base-type:
 8555     # . prologue
 8556     55/push-ebp
 8557     89/<- %ebp 4/r32/esp
 8558     # setup
 8559     (clear-stream _test-input-stream)
 8560     (clear-stream $_test-input-buffered-file->buffer)
 8561     (clear-stream _test-output-stream)
 8562     (clear-stream $_test-output-buffered-file->buffer)
 8563     (clear-stream _test-error-stream)
 8564     (clear-stream $_test-error-buffered-file->buffer)
 8565     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8566     68/push 0/imm32
 8567     68/push 0/imm32
 8568     89/<- %edx 4/r32/esp
 8569     (tailor-exit-descriptor %edx 0x10)
 8570     #
 8571     (write _test-input-stream "fn foo {\n")
 8572     (write _test-input-stream "  var a: (handle int)\n")
 8573     (write _test-input-stream "  read-from-stream a, 0\n")
 8574     (write _test-input-stream "}\n")
 8575     # convert
 8576     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8577     # registers except esp clobbered at this point
 8578     # restore ed
 8579     89/<- %edx 4/r32/esp
 8580     (flush _test-output-buffered-file)
 8581     (flush _test-error-buffered-file)
 8582 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8588     # check output
 8589     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-non-stream-compound-base-type: output should be empty")
 8590     (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")
 8591     # check that stop(1) was called
 8592     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-non-stream-compound-base-type: exit status")
 8593     # don't restore from ebp
 8594     81 0/subop/add %esp 8/imm32
 8595     # . epilogue
 8596     5d/pop-to-ebp
 8597     c3/return
 8598 
 8599 test-read-from-stream-with-non-stream-compound-base-type-2:
 8600     # . prologue
 8601     55/push-ebp
 8602     89/<- %ebp 4/r32/esp
 8603     # setup
 8604     (clear-stream _test-input-stream)
 8605     (clear-stream $_test-input-buffered-file->buffer)
 8606     (clear-stream _test-output-stream)
 8607     (clear-stream $_test-output-buffered-file->buffer)
 8608     (clear-stream _test-error-stream)
 8609     (clear-stream $_test-error-buffered-file->buffer)
 8610     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8611     68/push 0/imm32
 8612     68/push 0/imm32
 8613     89/<- %edx 4/r32/esp
 8614     (tailor-exit-descriptor %edx 0x10)
 8615     #
 8616     (write _test-input-stream "fn foo {\n")
 8617     (write _test-input-stream "  var a: (addr int)\n")
 8618     (write _test-input-stream "  read-from-stream a, 0\n")
 8619     (write _test-input-stream "}\n")
 8620     # convert
 8621     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8622     # registers except esp clobbered at this point
 8623     # restore ed
 8624     89/<- %edx 4/r32/esp
 8625     (flush _test-output-buffered-file)
 8626     (flush _test-error-buffered-file)
 8627 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8633     # check output
 8634     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-non-stream-compound-base-type-2: output should be empty")
 8635     (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")
 8636     # check that stop(1) was called
 8637     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-non-stream-compound-base-type-2: exit status")
 8638     # don't restore from ebp
 8639     81 0/subop/add %esp 8/imm32
 8640     # . epilogue
 8641     5d/pop-to-ebp
 8642     c3/return
 8643 
 8644 test-read-from-stream-with-stream-atom-base-type:
 8645     # . prologue
 8646     55/push-ebp
 8647     89/<- %ebp 4/r32/esp
 8648     # setup
 8649     (clear-stream _test-input-stream)
 8650     (clear-stream $_test-input-buffered-file->buffer)
 8651     (clear-stream _test-output-stream)
 8652     (clear-stream $_test-output-buffered-file->buffer)
 8653     (clear-stream _test-error-stream)
 8654     (clear-stream $_test-error-buffered-file->buffer)
 8655     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8656     68/push 0/imm32
 8657     68/push 0/imm32
 8658     89/<- %edx 4/r32/esp
 8659     (tailor-exit-descriptor %edx 0x10)
 8660     #
 8661     (write _test-input-stream "fn foo {\n")
 8662     (write _test-input-stream "  var a: stream\n")
 8663     (write _test-input-stream "  read-from-stream a, 0\n")
 8664     (write _test-input-stream "}\n")
 8665     # convert
 8666     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8667     # registers except esp clobbered at this point
 8668     # restore ed
 8669     89/<- %edx 4/r32/esp
 8670     (flush _test-output-buffered-file)
 8671     (flush _test-error-buffered-file)
 8672 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8678     # check output
 8679     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-stream-atom-base-type: output should be empty")
 8680     (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")
 8681     # check that stop(1) was called
 8682     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-stream-atom-base-type: exit status")
 8683     # don't restore from ebp
 8684     81 0/subop/add %esp 8/imm32
 8685     # . epilogue
 8686     5d/pop-to-ebp
 8687     c3/return
 8688 
 8689 test-read-from-stream-with-wrong-index-type:
 8690     # . prologue
 8691     55/push-ebp
 8692     89/<- %ebp 4/r32/esp
 8693     # setup
 8694     (clear-stream _test-input-stream)
 8695     (clear-stream $_test-input-buffered-file->buffer)
 8696     (clear-stream _test-output-stream)
 8697     (clear-stream $_test-output-buffered-file->buffer)
 8698     (clear-stream _test-error-stream)
 8699     (clear-stream $_test-error-buffered-file->buffer)
 8700     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8701     68/push 0/imm32
 8702     68/push 0/imm32
 8703     89/<- %edx 4/r32/esp
 8704     (tailor-exit-descriptor %edx 0x10)
 8705     #
 8706     (write _test-input-stream "fn foo {\n")
 8707     (write _test-input-stream "  var a/eax: (addr stream int) <- copy 0\n")
 8708     (write _test-input-stream "  var b: boolean\n")
 8709     (write _test-input-stream "  read-from-stream a, b\n")
 8710     (write _test-input-stream "}\n")
 8711     # convert
 8712     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8713     # registers except esp clobbered at this point
 8714     # restore ed
 8715     89/<- %edx 4/r32/esp
 8716     (flush _test-output-buffered-file)
 8717     (flush _test-error-buffered-file)
 8718 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8724     # check output
 8725     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-wrong-index-type: output should be empty")
 8726     (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")
 8727     # check that stop(1) was called
 8728     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-wrong-index-type: exit status")
 8729     # don't restore from ebp
 8730     81 0/subop/add %esp 8/imm32
 8731     # . epilogue
 8732     5d/pop-to-ebp
 8733     c3/return
 8734 
 8735 test-read-from-stream-with-no-inouts:
 8736     # . prologue
 8737     55/push-ebp
 8738     89/<- %ebp 4/r32/esp
 8739     # setup
 8740     (clear-stream _test-input-stream)
 8741     (clear-stream $_test-input-buffered-file->buffer)
 8742     (clear-stream _test-output-stream)
 8743     (clear-stream $_test-output-buffered-file->buffer)
 8744     (clear-stream _test-error-stream)
 8745     (clear-stream $_test-error-buffered-file->buffer)
 8746     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8747     68/push 0/imm32
 8748     68/push 0/imm32
 8749     89/<- %edx 4/r32/esp
 8750     (tailor-exit-descriptor %edx 0x10)
 8751     #
 8752     (write _test-input-stream "fn foo {\n")
 8753     (write _test-input-stream "  read-from-stream\n")
 8754     (write _test-input-stream "}\n")
 8755     # convert
 8756     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8757     # registers except esp clobbered at this point
 8758     # restore ed
 8759     89/<- %edx 4/r32/esp
 8760     (flush _test-output-buffered-file)
 8761     (flush _test-error-buffered-file)
 8762 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8768     # check output
 8769     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-no-inouts: output should be empty")
 8770     (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")
 8771     # check that stop(1) was called
 8772     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-no-inouts: exit status")
 8773     # don't restore from ebp
 8774     81 0/subop/add %esp 8/imm32
 8775     # . epilogue
 8776     5d/pop-to-ebp
 8777     c3/return
 8778 
 8779 test-read-from-stream-with-too-few-inouts:
 8780     # . prologue
 8781     55/push-ebp
 8782     89/<- %ebp 4/r32/esp
 8783     # setup
 8784     (clear-stream _test-input-stream)
 8785     (clear-stream $_test-input-buffered-file->buffer)
 8786     (clear-stream _test-output-stream)
 8787     (clear-stream $_test-output-buffered-file->buffer)
 8788     (clear-stream _test-error-stream)
 8789     (clear-stream $_test-error-buffered-file->buffer)
 8790     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8791     68/push 0/imm32
 8792     68/push 0/imm32
 8793     89/<- %edx 4/r32/esp
 8794     (tailor-exit-descriptor %edx 0x10)
 8795     #
 8796     (write _test-input-stream "fn foo {\n")
 8797     (write _test-input-stream "  var a: (addr stream int)\n")
 8798     (write _test-input-stream "  read-from-stream a\n")
 8799     (write _test-input-stream "}\n")
 8800     # convert
 8801     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8802     # registers except esp clobbered at this point
 8803     # restore ed
 8804     89/<- %edx 4/r32/esp
 8805     (flush _test-output-buffered-file)
 8806     (flush _test-error-buffered-file)
 8807 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8813     # check output
 8814     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-too-few-inouts: output should be empty")
 8815     (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")
 8816     # check that stop(1) was called
 8817     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-too-few-inouts: exit status")
 8818     # don't restore from ebp
 8819     81 0/subop/add %esp 8/imm32
 8820     # . epilogue
 8821     5d/pop-to-ebp
 8822     c3/return
 8823 
 8824 test-read-from-stream-with-too-many-inouts:
 8825     # . prologue
 8826     55/push-ebp
 8827     89/<- %ebp 4/r32/esp
 8828     # setup
 8829     (clear-stream _test-input-stream)
 8830     (clear-stream $_test-input-buffered-file->buffer)
 8831     (clear-stream _test-output-stream)
 8832     (clear-stream $_test-output-buffered-file->buffer)
 8833     (clear-stream _test-error-stream)
 8834     (clear-stream $_test-error-buffered-file->buffer)
 8835     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8836     68/push 0/imm32
 8837     68/push 0/imm32
 8838     89/<- %edx 4/r32/esp
 8839     (tailor-exit-descriptor %edx 0x10)
 8840     #
 8841     (write _test-input-stream "fn foo {\n")
 8842     (write _test-input-stream "  var a: (addr stream int)\n")
 8843     (write _test-input-stream "  var b: (addr int)\n")
 8844     (write _test-input-stream "  read-from-stream a, b, 0\n")
 8845     (write _test-input-stream "}\n")
 8846     # convert
 8847     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8848     # registers except esp clobbered at this point
 8849     # restore ed
 8850     89/<- %edx 4/r32/esp
 8851     (flush _test-output-buffered-file)
 8852     (flush _test-error-buffered-file)
 8853 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8859     # check output
 8860     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-too-many-inouts: output should be empty")
 8861     (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")
 8862     # check that stop(1) was called
 8863     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-too-many-inouts: exit status")
 8864     # don't restore from ebp
 8865     81 0/subop/add %esp 8/imm32
 8866     # . epilogue
 8867     5d/pop-to-ebp
 8868     c3/return
 8869 
 8870 test-read-from-stream-with-output:
 8871     # . prologue
 8872     55/push-ebp
 8873     89/<- %ebp 4/r32/esp
 8874     # setup
 8875     (clear-stream _test-input-stream)
 8876     (clear-stream $_test-input-buffered-file->buffer)
 8877     (clear-stream _test-output-stream)
 8878     (clear-stream $_test-output-buffered-file->buffer)
 8879     (clear-stream _test-error-stream)
 8880     (clear-stream $_test-error-buffered-file->buffer)
 8881     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8882     68/push 0/imm32
 8883     68/push 0/imm32
 8884     89/<- %edx 4/r32/esp
 8885     (tailor-exit-descriptor %edx 0x10)
 8886     #
 8887     (write _test-input-stream "fn foo {\n")
 8888     (write _test-input-stream "  var a: (addr stream int)\n")
 8889     (write _test-input-stream "  var b/eax: (addr int) <- copy 0\n")
 8890     (write _test-input-stream "  b <- read-from-stream a, b\n")
 8891     (write _test-input-stream "}\n")
 8892     # convert
 8893     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8894     # registers except esp clobbered at this point
 8895     # restore ed
 8896     89/<- %edx 4/r32/esp
 8897     (flush _test-output-buffered-file)
 8898     (flush _test-error-buffered-file)
 8899 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8905     # check output
 8906     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-output: output should be empty")
 8907     (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")
 8908     # check that stop(1) was called
 8909     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-output: exit status")
 8910     # don't restore from ebp
 8911     81 0/subop/add %esp 8/imm32
 8912     # . epilogue
 8913     5d/pop-to-ebp
 8914     c3/return
 8915 
 8916 test-convert-write-to-stream:
 8917     # . prologue
 8918     55/push-ebp
 8919     89/<- %ebp 4/r32/esp
 8920     # setup
 8921     (clear-stream _test-input-stream)
 8922     (clear-stream $_test-input-buffered-file->buffer)
 8923     (clear-stream _test-output-stream)
 8924     (clear-stream $_test-output-buffered-file->buffer)
 8925     #
 8926     (write _test-input-stream "fn foo {\n")
 8927     (write _test-input-stream "  var s/esi: (addr stream int) <- copy 0\n")
 8928     (write _test-input-stream "  var o/ecx: (addr int) <- copy 0\n")
 8929     (write _test-input-stream "  write-to-stream s, o\n")
 8930     (write _test-input-stream "}\n")
 8931     # convert
 8932     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 8933     # registers except esp clobbered at this point
 8934     # restore ed
 8935     89/<- %edx 4/r32/esp
 8936     (flush _test-output-buffered-file)
 8937     (flush _test-error-buffered-file)
 8938 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8944     # check output
 8945     (check-next-stream-line-equal _test-output-stream "foo:"                            "F - test-convert-write-to-stream/0")
 8946     (check-next-stream-line-equal _test-output-stream "  # . prologue"                  "F - test-convert-write-to-stream/1")
 8947     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                   "F - test-convert-write-to-stream/2")
 8948     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"          "F - test-convert-write-to-stream/3")
 8949     (check-next-stream-line-equal _test-output-stream "  {"                             "F - test-convert-write-to-stream/4")
 8950     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"           "F - test-convert-write-to-stream/5")
 8951     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %esi"        "F - test-convert-write-to-stream/6")
 8952     (check-next-stream-line-equal _test-output-stream "    be/copy-to-esi 0/imm32"      "F - test-convert-write-to-stream/7")
 8953     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"        "F - test-convert-write-to-stream/8")
 8954     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"      "F - test-convert-write-to-stream/9")
 8955     (check-next-stream-line-equal _test-output-stream "    (write-to-stream %esi %ecx 0x00000004)"  "F - test-convert-write-to-stream/10")
 8956     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-write-to-stream/11")
 8957     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %esi"         "F - test-convert-write-to-stream/12")
 8958     (check-next-stream-line-equal _test-output-stream "  }"                             "F - test-convert-write-to-stream/13")
 8959     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"          "F - test-convert-write-to-stream/14")
 8960     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                  "F - test-convert-write-to-stream/15")
 8961     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"          "F - test-convert-write-to-stream/16")
 8962     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                 "F - test-convert-write-to-stream/17")
 8963     (check-next-stream-line-equal _test-output-stream "  c3/return"                     "F - test-convert-write-to-stream/18")
 8964     # . epilogue
 8965     89/<- %esp 5/r32/ebp
 8966     5d/pop-to-ebp
 8967     c3/return
 8968 
 8969 test-convert-write-to-stream-with-correct-payload-size:
 8970     # . prologue
 8971     55/push-ebp
 8972     89/<- %ebp 4/r32/esp
 8973     # setup
 8974     (clear-stream _test-input-stream)
 8975     (clear-stream $_test-input-buffered-file->buffer)
 8976     (clear-stream _test-output-stream)
 8977     (clear-stream $_test-output-buffered-file->buffer)
 8978     #
 8979     (write _test-input-stream "fn foo {\n")
 8980     (write _test-input-stream "  var s/esi: (addr stream handle int) <- copy 0\n")
 8981     (write _test-input-stream "  var o/ecx: (addr handle int) <- copy 0\n")
 8982     (write _test-input-stream "  write-to-stream s, o\n")
 8983     (write _test-input-stream "}\n")
 8984     # convert
 8985     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 8986     # registers except esp clobbered at this point
 8987     # restore ed
 8988     89/<- %edx 4/r32/esp
 8989     (flush _test-output-buffered-file)
 8990     (flush _test-error-buffered-file)
 8991 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8997     # check output
 8998     (check-next-stream-line-equal _test-output-stream "foo:"                            "F - test-convert-write-to-stream-with-correct-payload-size/0")
 8999     (check-next-stream-line-equal _test-output-stream "  # . prologue"                  "F - test-convert-write-to-stream-with-correct-payload-size/1")
 9000     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                   "F - test-convert-write-to-stream-with-correct-payload-size/2")
 9001     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"          "F - test-convert-write-to-stream-with-correct-payload-size/3")
 9002     (check-next-stream-line-equal _test-output-stream "  {"                             "F - test-convert-write-to-stream-with-correct-payload-size/4")
 9003     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"           "F - test-convert-write-to-stream-with-correct-payload-size/5")
 9004     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %esi"        "F - test-convert-write-to-stream-with-correct-payload-size/6")
 9005     (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")
 9006     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"        "F - test-convert-write-to-stream-with-correct-payload-size/8")
 9007     (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")
 9008     (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")
 9009     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-write-to-stream-with-correct-payload-size/11")
 9010     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %esi"         "F - test-convert-write-to-stream-with-correct-payload-size/12")
 9011     (check-next-stream-line-equal _test-output-stream "  }"                             "F - test-convert-write-to-stream-with-correct-payload-size/13")
 9012     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"          "F - test-convert-write-to-stream-with-correct-payload-size/14")
 9013     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                  "F - test-convert-write-to-stream-with-correct-payload-size/15")
 9014     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"          "F - test-convert-write-to-stream-with-correct-payload-size/16")
 9015     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                 "F - test-convert-write-to-stream-with-correct-payload-size/17")
 9016     (check-next-stream-line-equal _test-output-stream "  c3/return"                     "F - test-convert-write-to-stream-with-correct-payload-size/18")
 9017     # . epilogue
 9018     89/<- %esp 5/r32/ebp
 9019     5d/pop-to-ebp
 9020     c3/return
 9021 
 9022 test-write-to-stream-with-non-stream-atom-base-type:
 9023     # . prologue
 9024     55/push-ebp
 9025     89/<- %ebp 4/r32/esp
 9026     # setup
 9027     (clear-stream _test-input-stream)
 9028     (clear-stream $_test-input-buffered-file->buffer)
 9029     (clear-stream _test-output-stream)
 9030     (clear-stream $_test-output-buffered-file->buffer)
 9031     (clear-stream _test-error-stream)
 9032     (clear-stream $_test-error-buffered-file->buffer)
 9033     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9034     68/push 0/imm32
 9035     68/push 0/imm32
 9036     89/<- %edx 4/r32/esp
 9037     (tailor-exit-descriptor %edx 0x10)
 9038     #
 9039     (write _test-input-stream "fn foo {\n")
 9040     (write _test-input-stream "  var a: int\n")
 9041     (write _test-input-stream "  write-to-stream a, 0\n")
 9042     (write _test-input-stream "}\n")
 9043     # convert
 9044     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9045     # registers except esp clobbered at this point
 9046     # restore ed
 9047     89/<- %edx 4/r32/esp
 9048     (flush _test-output-buffered-file)
 9049     (flush _test-error-buffered-file)
 9050 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9056     # check output
 9057     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-non-stream-atom-base-type: output should be empty")
 9058     (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")
 9059     # check that stop(1) was called
 9060     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-non-stream-atom-base-type: exit status")
 9061     # don't restore from ebp
 9062     81 0/subop/add %esp 8/imm32
 9063     # . epilogue
 9064     5d/pop-to-ebp
 9065     c3/return
 9066 
 9067 test-write-to-stream-with-non-stream-compound-base-type:
 9068     # . prologue
 9069     55/push-ebp
 9070     89/<- %ebp 4/r32/esp
 9071     # setup
 9072     (clear-stream _test-input-stream)
 9073     (clear-stream $_test-input-buffered-file->buffer)
 9074     (clear-stream _test-output-stream)
 9075     (clear-stream $_test-output-buffered-file->buffer)
 9076     (clear-stream _test-error-stream)
 9077     (clear-stream $_test-error-buffered-file->buffer)
 9078     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9079     68/push 0/imm32
 9080     68/push 0/imm32
 9081     89/<- %edx 4/r32/esp
 9082     (tailor-exit-descriptor %edx 0x10)
 9083     #
 9084     (write _test-input-stream "fn foo {\n")
 9085     (write _test-input-stream "  var a: (handle int)\n")
 9086     (write _test-input-stream "  write-to-stream a, 0\n")
 9087     (write _test-input-stream "}\n")
 9088     # convert
 9089     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9090     # registers except esp clobbered at this point
 9091     # restore ed
 9092     89/<- %edx 4/r32/esp
 9093     (flush _test-output-buffered-file)
 9094     (flush _test-error-buffered-file)
 9095 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9101     # check output
 9102     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-non-stream-compound-base-type: output should be empty")
 9103     (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")
 9104     # check that stop(1) was called
 9105     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-non-stream-compound-base-type: exit status")
 9106     # don't restore from ebp
 9107     81 0/subop/add %esp 8/imm32
 9108     # . epilogue
 9109     5d/pop-to-ebp
 9110     c3/return
 9111 
 9112 test-write-to-stream-with-non-stream-compound-base-type-2:
 9113     # . prologue
 9114     55/push-ebp
 9115     89/<- %ebp 4/r32/esp
 9116     # setup
 9117     (clear-stream _test-input-stream)
 9118     (clear-stream $_test-input-buffered-file->buffer)
 9119     (clear-stream _test-output-stream)
 9120     (clear-stream $_test-output-buffered-file->buffer)
 9121     (clear-stream _test-error-stream)
 9122     (clear-stream $_test-error-buffered-file->buffer)
 9123     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9124     68/push 0/imm32
 9125     68/push 0/imm32
 9126     89/<- %edx 4/r32/esp
 9127     (tailor-exit-descriptor %edx 0x10)
 9128     #
 9129     (write _test-input-stream "fn foo {\n")
 9130     (write _test-input-stream "  var a: (addr int)\n")
 9131     (write _test-input-stream "  write-to-stream a, 0\n")
 9132     (write _test-input-stream "}\n")
 9133     # convert
 9134     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9135     # registers except esp clobbered at this point
 9136     # restore ed
 9137     89/<- %edx 4/r32/esp
 9138     (flush _test-output-buffered-file)
 9139     (flush _test-error-buffered-file)
 9140 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9146     # check output
 9147     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-non-stream-compound-base-type-2: output should be empty")
 9148     (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")
 9149     # check that stop(1) was called
 9150     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-non-stream-compound-base-type-2: exit status")
 9151     # don't restore from ebp
 9152     81 0/subop/add %esp 8/imm32
 9153     # . epilogue
 9154     5d/pop-to-ebp
 9155     c3/return
 9156 
 9157 test-write-to-stream-with-stream-atom-base-type:
 9158     # . prologue
 9159     55/push-ebp
 9160     89/<- %ebp 4/r32/esp
 9161     # setup
 9162     (clear-stream _test-input-stream)
 9163     (clear-stream $_test-input-buffered-file->buffer)
 9164     (clear-stream _test-output-stream)
 9165     (clear-stream $_test-output-buffered-file->buffer)
 9166     (clear-stream _test-error-stream)
 9167     (clear-stream $_test-error-buffered-file->buffer)
 9168     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9169     68/push 0/imm32
 9170     68/push 0/imm32
 9171     89/<- %edx 4/r32/esp
 9172     (tailor-exit-descriptor %edx 0x10)
 9173     #
 9174     (write _test-input-stream "fn foo {\n")
 9175     (write _test-input-stream "  var a: stream\n")
 9176     (write _test-input-stream "  write-to-stream a, 0\n")
 9177     (write _test-input-stream "}\n")
 9178     # convert
 9179     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9180     # registers except esp clobbered at this point
 9181     # restore ed
 9182     89/<- %edx 4/r32/esp
 9183     (flush _test-output-buffered-file)
 9184     (flush _test-error-buffered-file)
 9185 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9191     # check output
 9192     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-stream-atom-base-type: output should be empty")
 9193     (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")
 9194     # check that stop(1) was called
 9195     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-stream-atom-base-type: exit status")
 9196     # don't restore from ebp
 9197     81 0/subop/add %esp 8/imm32
 9198     # . epilogue
 9199     5d/pop-to-ebp
 9200     c3/return
 9201 
 9202 test-write-to-stream-with-wrong-index-type:
 9203     # . prologue
 9204     55/push-ebp
 9205     89/<- %ebp 4/r32/esp
 9206     # setup
 9207     (clear-stream _test-input-stream)
 9208     (clear-stream $_test-input-buffered-file->buffer)
 9209     (clear-stream _test-output-stream)
 9210     (clear-stream $_test-output-buffered-file->buffer)
 9211     (clear-stream _test-error-stream)
 9212     (clear-stream $_test-error-buffered-file->buffer)
 9213     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9214     68/push 0/imm32
 9215     68/push 0/imm32
 9216     89/<- %edx 4/r32/esp
 9217     (tailor-exit-descriptor %edx 0x10)
 9218     #
 9219     (write _test-input-stream "fn foo {\n")
 9220     (write _test-input-stream "  var a/eax: (addr stream int) <- copy 0\n")
 9221     (write _test-input-stream "  var b: boolean\n")
 9222     (write _test-input-stream "  write-to-stream a, b\n")
 9223     (write _test-input-stream "}\n")
 9224     # convert
 9225     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9226     # registers except esp clobbered at this point
 9227     # restore ed
 9228     89/<- %edx 4/r32/esp
 9229     (flush _test-output-buffered-file)
 9230     (flush _test-error-buffered-file)
 9231 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9237     # check output
 9238     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-wrong-index-type: output should be empty")
 9239     (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")
 9240     # check that stop(1) was called
 9241     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-wrong-index-type: exit status")
 9242     # don't restore from ebp
 9243     81 0/subop/add %esp 8/imm32
 9244     # . epilogue
 9245     5d/pop-to-ebp
 9246     c3/return
 9247 
 9248 test-write-to-stream-with-no-inouts:
 9249     # . prologue
 9250     55/push-ebp
 9251     89/<- %ebp 4/r32/esp
 9252     # setup
 9253     (clear-stream _test-input-stream)
 9254     (clear-stream $_test-input-buffered-file->buffer)
 9255     (clear-stream _test-output-stream)
 9256     (clear-stream $_test-output-buffered-file->buffer)
 9257     (clear-stream _test-error-stream)
 9258     (clear-stream $_test-error-buffered-file->buffer)
 9259     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9260     68/push 0/imm32
 9261     68/push 0/imm32
 9262     89/<- %edx 4/r32/esp
 9263     (tailor-exit-descriptor %edx 0x10)
 9264     #
 9265     (write _test-input-stream "fn foo {\n")
 9266     (write _test-input-stream "  write-to-stream\n")
 9267     (write _test-input-stream "}\n")
 9268     # convert
 9269     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9270     # registers except esp clobbered at this point
 9271     # restore ed
 9272     89/<- %edx 4/r32/esp
 9273     (flush _test-output-buffered-file)
 9274     (flush _test-error-buffered-file)
 9275 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9281     # check output
 9282     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-no-inouts: output should be empty")
 9283     (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")
 9284     # check that stop(1) was called
 9285     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-no-inouts: exit status")
 9286     # don't restore from ebp
 9287     81 0/subop/add %esp 8/imm32
 9288     # . epilogue
 9289     5d/pop-to-ebp
 9290     c3/return
 9291 
 9292 test-write-to-stream-with-too-few-inouts:
 9293     # . prologue
 9294     55/push-ebp
 9295     89/<- %ebp 4/r32/esp
 9296     # setup
 9297     (clear-stream _test-input-stream)
 9298     (clear-stream $_test-input-buffered-file->buffer)
 9299     (clear-stream _test-output-stream)
 9300     (clear-stream $_test-output-buffered-file->buffer)
 9301     (clear-stream _test-error-stream)
 9302     (clear-stream $_test-error-buffered-file->buffer)
 9303     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9304     68/push 0/imm32
 9305     68/push 0/imm32
 9306     89/<- %edx 4/r32/esp
 9307     (tailor-exit-descriptor %edx 0x10)
 9308     #
 9309     (write _test-input-stream "fn foo {\n")
 9310     (write _test-input-stream "  var a: (addr stream int)\n")
 9311     (write _test-input-stream "  write-to-stream a\n")
 9312     (write _test-input-stream "}\n")
 9313     # convert
 9314     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9315     # registers except esp clobbered at this point
 9316     # restore ed
 9317     89/<- %edx 4/r32/esp
 9318     (flush _test-output-buffered-file)
 9319     (flush _test-error-buffered-file)
 9320 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9326     # check output
 9327     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-too-few-inouts: output should be empty")
 9328     (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")
 9329     # check that stop(1) was called
 9330     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-too-few-inouts: exit status")
 9331     # don't restore from ebp
 9332     81 0/subop/add %esp 8/imm32
 9333     # . epilogue
 9334     5d/pop-to-ebp
 9335     c3/return
 9336 
 9337 test-write-to-stream-with-too-many-inouts:
 9338     # . prologue
 9339     55/push-ebp
 9340     89/<- %ebp 4/r32/esp
 9341     # setup
 9342     (clear-stream _test-input-stream)
 9343     (clear-stream $_test-input-buffered-file->buffer)
 9344     (clear-stream _test-output-stream)
 9345     (clear-stream $_test-output-buffered-file->buffer)
 9346     (clear-stream _test-error-stream)
 9347     (clear-stream $_test-error-buffered-file->buffer)
 9348     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9349     68/push 0/imm32
 9350     68/push 0/imm32
 9351     89/<- %edx 4/r32/esp
 9352     (tailor-exit-descriptor %edx 0x10)
 9353     #
 9354     (write _test-input-stream "fn foo {\n")
 9355     (write _test-input-stream "  var a: (addr stream int)\n")
 9356     (write _test-input-stream "  var b: (addr int)\n")
 9357     (write _test-input-stream "  write-to-stream a, b, 0\n")
 9358     (write _test-input-stream "}\n")
 9359     # convert
 9360     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9361     # registers except esp clobbered at this point
 9362     # restore ed
 9363     89/<- %edx 4/r32/esp
 9364     (flush _test-output-buffered-file)
 9365     (flush _test-error-buffered-file)
 9366 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9372     # check output
 9373     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-too-many-inouts: output should be empty")
 9374     (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")
 9375     # check that stop(1) was called
 9376     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-too-many-inouts: exit status")
 9377     # don't restore from ebp
 9378     81 0/subop/add %esp 8/imm32
 9379     # . epilogue
 9380     5d/pop-to-ebp
 9381     c3/return
 9382 
 9383 test-write-to-stream-with-output:
 9384     # . prologue
 9385     55/push-ebp
 9386     89/<- %ebp 4/r32/esp
 9387     # setup
 9388     (clear-stream _test-input-stream)
 9389     (clear-stream $_test-input-buffered-file->buffer)
 9390     (clear-stream _test-output-stream)
 9391     (clear-stream $_test-output-buffered-file->buffer)
 9392     (clear-stream _test-error-stream)
 9393     (clear-stream $_test-error-buffered-file->buffer)
 9394     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9395     68/push 0/imm32
 9396     68/push 0/imm32
 9397     89/<- %edx 4/r32/esp
 9398     (tailor-exit-descriptor %edx 0x10)
 9399     #
 9400     (write _test-input-stream "fn foo {\n")
 9401     (write _test-input-stream "  var a: (addr stream int)\n")
 9402     (write _test-input-stream "  var b/eax: (addr int) <- copy 0\n")
 9403     (write _test-input-stream "  b <- write-to-stream a, b\n")
 9404     (write _test-input-stream "}\n")
 9405     # convert
 9406     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9407     # registers except esp clobbered at this point
 9408     # restore ed
 9409     89/<- %edx 4/r32/esp
 9410     (flush _test-output-buffered-file)
 9411     (flush _test-error-buffered-file)
 9412 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9418     # check output
 9419     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-output: output should be empty")
 9420     (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")
 9421     # check that stop(1) was called
 9422     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-output: exit status")
 9423     # don't restore from ebp
 9424     81 0/subop/add %esp 8/imm32
 9425     # . epilogue
 9426     5d/pop-to-ebp
 9427     c3/return
 9428 
 9429 test-length-with-non-array-atom-base-type:
 9430     # . prologue
 9431     55/push-ebp
 9432     89/<- %ebp 4/r32/esp
 9433     # setup
 9434     (clear-stream _test-input-stream)
 9435     (clear-stream $_test-input-buffered-file->buffer)
 9436     (clear-stream _test-output-stream)
 9437     (clear-stream $_test-output-buffered-file->buffer)
 9438     (clear-stream _test-error-stream)
 9439     (clear-stream $_test-error-buffered-file->buffer)
 9440     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9441     68/push 0/imm32
 9442     68/push 0/imm32
 9443     89/<- %edx 4/r32/esp
 9444     (tailor-exit-descriptor %edx 0x10)
 9445     #
 9446     (write _test-input-stream "fn foo {\n")
 9447     (write _test-input-stream "  var a: int\n")
 9448     (write _test-input-stream "  var c/ecx: int <- length a\n")
 9449     (write _test-input-stream "}\n")
 9450     # convert
 9451     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9452     # registers except esp clobbered at this point
 9453     # restore ed
 9454     89/<- %edx 4/r32/esp
 9455     (flush _test-output-buffered-file)
 9456     (flush _test-error-buffered-file)
 9457 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9463     # check output
 9464     (check-stream-equal _test-output-stream  ""  "F - test-length-with-non-array-atom-base-type: output should be empty")
 9465     (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")
 9466     # check that stop(1) was called
 9467     (check-ints-equal *(edx+4) 2 "F - test-length-with-non-array-atom-base-type: exit status")
 9468     # don't restore from ebp
 9469     81 0/subop/add %esp 8/imm32
 9470     # . epilogue
 9471     5d/pop-to-ebp
 9472     c3/return
 9473 
 9474 test-length-with-non-array-compound-base-type:
 9475     # . prologue
 9476     55/push-ebp
 9477     89/<- %ebp 4/r32/esp
 9478     # setup
 9479     (clear-stream _test-input-stream)
 9480     (clear-stream $_test-input-buffered-file->buffer)
 9481     (clear-stream _test-output-stream)
 9482     (clear-stream $_test-output-buffered-file->buffer)
 9483     (clear-stream _test-error-stream)
 9484     (clear-stream $_test-error-buffered-file->buffer)
 9485     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9486     68/push 0/imm32
 9487     68/push 0/imm32
 9488     89/<- %edx 4/r32/esp
 9489     (tailor-exit-descriptor %edx 0x10)
 9490     #
 9491     (write _test-input-stream "fn foo {\n")
 9492     (write _test-input-stream "  var a: (handle int)\n")
 9493     (write _test-input-stream "  var c/ecx: (addr int) <- length a, 0\n")
 9494     (write _test-input-stream "}\n")
 9495     # convert
 9496     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9497     # registers except esp clobbered at this point
 9498     # restore ed
 9499     89/<- %edx 4/r32/esp
 9500     (flush _test-output-buffered-file)
 9501     (flush _test-error-buffered-file)
 9502 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9508     # check output
 9509     (check-stream-equal _test-output-stream  ""  "F - test-length-with-non-array-compound-base-type: output should be empty")
 9510     (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")
 9511     # check that stop(1) was called
 9512     (check-ints-equal *(edx+4) 2 "F - test-length-with-non-array-compound-base-type: exit status")
 9513     # don't restore from ebp
 9514     81 0/subop/add %esp 8/imm32
 9515     # . epilogue
 9516     5d/pop-to-ebp
 9517     c3/return
 9518 
 9519 test-length-with-non-array-compound-base-type-2:
 9520     # . prologue
 9521     55/push-ebp
 9522     89/<- %ebp 4/r32/esp
 9523     # setup
 9524     (clear-stream _test-input-stream)
 9525     (clear-stream $_test-input-buffered-file->buffer)
 9526     (clear-stream _test-output-stream)
 9527     (clear-stream $_test-output-buffered-file->buffer)
 9528     (clear-stream _test-error-stream)
 9529     (clear-stream $_test-error-buffered-file->buffer)
 9530     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9531     68/push 0/imm32
 9532     68/push 0/imm32
 9533     89/<- %edx 4/r32/esp
 9534     (tailor-exit-descriptor %edx 0x10)
 9535     #
 9536     (write _test-input-stream "fn foo {\n")
 9537     (write _test-input-stream "  var a: (addr int)\n")
 9538     (write _test-input-stream "  var c/ecx: (addr int) <- length a, 0\n")
 9539     (write _test-input-stream "}\n")
 9540     # convert
 9541     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9542     # registers except esp clobbered at this point
 9543     # restore ed
 9544     89/<- %edx 4/r32/esp
 9545     (flush _test-output-buffered-file)
 9546     (flush _test-error-buffered-file)
 9547 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9553     # check output
 9554     (check-stream-equal _test-output-stream  ""  "F - test-length-with-non-array-compound-base-type-2: output should be empty")
 9555     (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")
 9556     # check that stop(1) was called
 9557     (check-ints-equal *(edx+4) 2 "F - test-length-with-non-array-compound-base-type-2: exit status")
 9558     # don't restore from ebp
 9559     81 0/subop/add %esp 8/imm32
 9560     # . epilogue
 9561     5d/pop-to-ebp
 9562     c3/return
 9563 
 9564 test-length-with-array-atom-base-type:
 9565     # . prologue
 9566     55/push-ebp
 9567     89/<- %ebp 4/r32/esp
 9568     # setup
 9569     (clear-stream _test-input-stream)
 9570     (clear-stream $_test-input-buffered-file->buffer)
 9571     (clear-stream _test-output-stream)
 9572     (clear-stream $_test-output-buffered-file->buffer)
 9573     (clear-stream _test-error-stream)
 9574     (clear-stream $_test-error-buffered-file->buffer)
 9575     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9576     68/push 0/imm32
 9577     68/push 0/imm32
 9578     89/<- %edx 4/r32/esp
 9579     (tailor-exit-descriptor %edx 0x10)
 9580     #
 9581     (write _test-input-stream "fn foo {\n")
 9582     (write _test-input-stream "  var a: array\n")
 9583     (write _test-input-stream "  var c/ecx: (addr int) <- length a\n")
 9584     (write _test-input-stream "}\n")
 9585     # convert
 9586     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9587     # registers except esp clobbered at this point
 9588     # restore ed
 9589     89/<- %edx 4/r32/esp
 9590     (flush _test-output-buffered-file)
 9591     (flush _test-error-buffered-file)
 9592 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9598     # check output
 9599     (check-stream-equal _test-output-stream  ""  "F - test-length-with-array-atom-base-type: output should be empty")
 9600     (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")
 9601     # check that stop(1) was called
 9602     (check-ints-equal *(edx+4) 2 "F - test-length-with-array-atom-base-type: exit status")
 9603     # don't restore from ebp
 9604     81 0/subop/add %esp 8/imm32
 9605     # . epilogue
 9606     5d/pop-to-ebp
 9607     c3/return
 9608 
 9609 test-length-with-addr-base-on-stack:
 9610     # . prologue
 9611     55/push-ebp
 9612     89/<- %ebp 4/r32/esp
 9613     # setup
 9614     (clear-stream _test-input-stream)
 9615     (clear-stream $_test-input-buffered-file->buffer)
 9616     (clear-stream _test-output-stream)
 9617     (clear-stream $_test-output-buffered-file->buffer)
 9618     (clear-stream _test-error-stream)
 9619     (clear-stream $_test-error-buffered-file->buffer)
 9620     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9621     68/push 0/imm32
 9622     68/push 0/imm32
 9623     89/<- %edx 4/r32/esp
 9624     (tailor-exit-descriptor %edx 0x10)
 9625     #
 9626     (write _test-input-stream "fn foo {\n")
 9627     (write _test-input-stream "  var a: (addr array int)\n")
 9628     (write _test-input-stream "  var c/ecx: (addr int) <- length a\n")
 9629     (write _test-input-stream "}\n")
 9630     # convert
 9631     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9632     # registers except esp clobbered at this point
 9633     # restore ed
 9634     89/<- %edx 4/r32/esp
 9635     (flush _test-output-buffered-file)
 9636     (flush _test-error-buffered-file)
 9637 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9643     # check output
 9644     (check-stream-equal _test-output-stream  ""  "F - test-length-with-addr-base-on-stack: output should be empty")
 9645     (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")
 9646     # check that stop(1) was called
 9647     (check-ints-equal *(edx+4) 2 "F - test-length-with-addr-base-on-stack: exit status")
 9648     # don't restore from ebp
 9649     81 0/subop/add %esp 8/imm32
 9650     # . epilogue
 9651     5d/pop-to-ebp
 9652     c3/return
 9653 
 9654 test-length-with-array-base-in-register:
 9655     # . prologue
 9656     55/push-ebp
 9657     89/<- %ebp 4/r32/esp
 9658     # setup
 9659     (clear-stream _test-input-stream)
 9660     (clear-stream $_test-input-buffered-file->buffer)
 9661     (clear-stream _test-output-stream)
 9662     (clear-stream $_test-output-buffered-file->buffer)
 9663     (clear-stream _test-error-stream)
 9664     (clear-stream $_test-error-buffered-file->buffer)
 9665     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9666     68/push 0/imm32
 9667     68/push 0/imm32
 9668     89/<- %edx 4/r32/esp
 9669     (tailor-exit-descriptor %edx 0x10)
 9670     #
 9671     (write _test-input-stream "fn foo {\n")
 9672     (write _test-input-stream "  var a/eax: (array int 3) <- copy 0\n")
 9673     (write _test-input-stream "  var c/ecx: (addr int) <- length a\n")
 9674     (write _test-input-stream "}\n")
 9675     # convert
 9676     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9677     # registers except esp clobbered at this point
 9678     # restore ed
 9679     89/<- %edx 4/r32/esp
 9680     (flush _test-output-buffered-file)
 9681     (flush _test-error-buffered-file)
 9682 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9688     # check output
 9689     (check-stream-equal _test-output-stream  ""  "F - test-length-with-array-base-in-register: output should be empty")
 9690     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt length: var 'a' is an array, and so must live on the stack"  "F - test-length-with-array-base-in-register: error message")
 9691     # check that stop(1) was called
 9692     (check-ints-equal *(edx+4) 2 "F - test-length-with-array-base-in-register: exit status")
 9693     # don't restore from ebp
 9694     81 0/subop/add %esp 8/imm32
 9695     # . epilogue
 9696     5d/pop-to-ebp
 9697     c3/return
 9698 
 9699 test-length-with-wrong-output-type:
 9700     # . prologue
 9701     55/push-ebp
 9702     89/<- %ebp 4/r32/esp
 9703     # setup
 9704     (clear-stream _test-input-stream)
 9705     (clear-stream $_test-input-buffered-file->buffer)
 9706     (clear-stream _test-output-stream)
 9707     (clear-stream $_test-output-buffered-file->buffer)
 9708     (clear-stream _test-error-stream)
 9709     (clear-stream $_test-error-buffered-file->buffer)
 9710     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9711     68/push 0/imm32
 9712     68/push 0/imm32
 9713     89/<- %edx 4/r32/esp
 9714     (tailor-exit-descriptor %edx 0x10)
 9715     #
 9716     (write _test-input-stream "fn foo {\n")
 9717     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
 9718     (write _test-input-stream "  var o/edi: (addr int) <- length a\n")
 9719     (write _test-input-stream "}\n")
 9720     # convert
 9721     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9722     # registers except esp clobbered at this point
 9723     # restore ed
 9724     89/<- %edx 4/r32/esp
 9725     (flush _test-output-buffered-file)
 9726     (flush _test-error-buffered-file)
 9727 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9733     # check output
 9734     (check-stream-equal _test-output-stream  ""  "F - test-length-with-wrong-output-type: output should be empty")
 9735     (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")
 9736     # check that stop(1) was called
 9737     (check-ints-equal *(edx+4) 2 "F - test-length-with-wrong-output-type: exit status")
 9738     # don't restore from ebp
 9739     81 0/subop/add %esp 8/imm32
 9740     # . epilogue
 9741     5d/pop-to-ebp
 9742     c3/return
 9743 
 9744 test-length-with-wrong-output-compound-type:
 9745     # . prologue
 9746     55/push-ebp
 9747     89/<- %ebp 4/r32/esp
 9748     # setup
 9749     (clear-stream _test-input-stream)
 9750     (clear-stream $_test-input-buffered-file->buffer)
 9751     (clear-stream _test-output-stream)
 9752     (clear-stream $_test-output-buffered-file->buffer)
 9753     (clear-stream _test-error-stream)
 9754     (clear-stream $_test-error-buffered-file->buffer)
 9755     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9756     68/push 0/imm32
 9757     68/push 0/imm32
 9758     89/<- %edx 4/r32/esp
 9759     (tailor-exit-descriptor %edx 0x10)
 9760     #
 9761     (write _test-input-stream "fn foo {\n")
 9762     (write _test-input-stream "  var a/ebx: (addr array handle boolean) <- copy 0\n")
 9763     (write _test-input-stream "  var o/edi: (addr handle int) <- length a\n")
 9764     (write _test-input-stream "}\n")
 9765     # convert
 9766     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9767     # registers except esp clobbered at this point
 9768     # restore ed
 9769     89/<- %edx 4/r32/esp
 9770     (flush _test-output-buffered-file)
 9771     (flush _test-error-buffered-file)
 9772 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9778     # check output
 9779     (check-stream-equal _test-output-stream  ""  "F - test-length-with-wrong-output-compound-type: output should be empty")
 9780     (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")
 9781     # check that stop(1) was called
 9782     (check-ints-equal *(edx+4) 2 "F - test-length-with-wrong-output-compound-type: exit status")
 9783     # don't restore from ebp
 9784     81 0/subop/add %esp 8/imm32
 9785     # . epilogue
 9786     5d/pop-to-ebp
 9787     c3/return
 9788 
 9789 test-length-with-no-inouts:
 9790     # . prologue
 9791     55/push-ebp
 9792     89/<- %ebp 4/r32/esp
 9793     # setup
 9794     (clear-stream _test-input-stream)
 9795     (clear-stream $_test-input-buffered-file->buffer)
 9796     (clear-stream _test-output-stream)
 9797     (clear-stream $_test-output-buffered-file->buffer)
 9798     (clear-stream _test-error-stream)
 9799     (clear-stream $_test-error-buffered-file->buffer)
 9800     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9801     68/push 0/imm32
 9802     68/push 0/imm32
 9803     89/<- %edx 4/r32/esp
 9804     (tailor-exit-descriptor %edx 0x10)
 9805     #
 9806     (write _test-input-stream "fn foo {\n")
 9807     (write _test-input-stream "  var c/ecx: int <- length\n")
 9808     (write _test-input-stream "}\n")
 9809     # convert
 9810     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9811     # registers except esp clobbered at this point
 9812     # restore ed
 9813     89/<- %edx 4/r32/esp
 9814     (flush _test-output-buffered-file)
 9815     (flush _test-error-buffered-file)
 9816 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9822     # check output
 9823     (check-stream-equal _test-output-stream  ""  "F - test-length-with-no-inouts: output should be empty")
 9824     (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")
 9825     # check that stop(1) was called
 9826     (check-ints-equal *(edx+4) 2 "F - test-length-with-no-inouts: exit status")
 9827     # don't restore from ebp
 9828     81 0/subop/add %esp 8/imm32
 9829     # . epilogue
 9830     5d/pop-to-ebp
 9831     c3/return
 9832 
 9833 test-length-with-too-many-inouts:
 9834     # . prologue
 9835     55/push-ebp
 9836     89/<- %ebp 4/r32/esp
 9837     # setup
 9838     (clear-stream _test-input-stream)
 9839     (clear-stream $_test-input-buffered-file->buffer)
 9840     (clear-stream _test-output-stream)
 9841     (clear-stream $_test-output-buffered-file->buffer)
 9842     (clear-stream _test-error-stream)
 9843     (clear-stream $_test-error-buffered-file->buffer)
 9844     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9845     68/push 0/imm32
 9846     68/push 0/imm32
 9847     89/<- %edx 4/r32/esp
 9848     (tailor-exit-descriptor %edx 0x10)
 9849     #
 9850     (write _test-input-stream "fn foo {\n")
 9851     (write _test-input-stream "  var a: (array int 3)\n")
 9852     (write _test-input-stream "  var c/ecx: int <- length a, 0, 0\n")
 9853     (write _test-input-stream "}\n")
 9854     # convert
 9855     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9856     # registers except esp clobbered at this point
 9857     # restore ed
 9858     89/<- %edx 4/r32/esp
 9859     (flush _test-output-buffered-file)
 9860     (flush _test-error-buffered-file)
 9861 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9867     # check output
 9868     (check-stream-equal _test-output-stream  ""  "F - test-length-with-too-many-inouts: output should be empty")
 9869     (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")
 9870     # check that stop(1) was called
 9871     (check-ints-equal *(edx+4) 2 "F - test-length-with-too-many-inouts: exit status")
 9872     # don't restore from ebp
 9873     81 0/subop/add %esp 8/imm32
 9874     # . epilogue
 9875     5d/pop-to-ebp
 9876     c3/return
 9877 
 9878 test-length-with-no-output:
 9879     # . prologue
 9880     55/push-ebp
 9881     89/<- %ebp 4/r32/esp
 9882     # setup
 9883     (clear-stream _test-input-stream)
 9884     (clear-stream $_test-input-buffered-file->buffer)
 9885     (clear-stream _test-output-stream)
 9886     (clear-stream $_test-output-buffered-file->buffer)
 9887     (clear-stream _test-error-stream)
 9888     (clear-stream $_test-error-buffered-file->buffer)
 9889     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9890     68/push 0/imm32
 9891     68/push 0/imm32
 9892     89/<- %edx 4/r32/esp
 9893     (tailor-exit-descriptor %edx 0x10)
 9894     #
 9895     (write _test-input-stream "fn foo {\n")
 9896     (write _test-input-stream "  var a: (array int 3)\n")
 9897     (write _test-input-stream "  length a\n")
 9898     (write _test-input-stream "}\n")
 9899     # convert
 9900     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9901     # registers except esp clobbered at this point
 9902     # restore ed
 9903     89/<- %edx 4/r32/esp
 9904     (flush _test-output-buffered-file)
 9905     (flush _test-error-buffered-file)
 9906 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9912     # check output
 9913     (check-stream-equal _test-output-stream  ""  "F - test-length-with-no-output: output should be empty")
 9914     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt length: must have an output"  "F - test-length-with-no-output: error message")
 9915     # check that stop(1) was called
 9916     (check-ints-equal *(edx+4) 2 "F - test-length-with-no-output: exit status")
 9917     # don't restore from ebp
 9918     81 0/subop/add %esp 8/imm32
 9919     # . epilogue
 9920     5d/pop-to-ebp
 9921     c3/return
 9922 
 9923 test-length-with-too-many-outputs:
 9924     # . prologue
 9925     55/push-ebp
 9926     89/<- %ebp 4/r32/esp
 9927     # setup
 9928     (clear-stream _test-input-stream)
 9929     (clear-stream $_test-input-buffered-file->buffer)
 9930     (clear-stream _test-output-stream)
 9931     (clear-stream $_test-output-buffered-file->buffer)
 9932     (clear-stream _test-error-stream)
 9933     (clear-stream $_test-error-buffered-file->buffer)
 9934     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9935     68/push 0/imm32
 9936     68/push 0/imm32
 9937     89/<- %edx 4/r32/esp
 9938     (tailor-exit-descriptor %edx 0x10)
 9939     #
 9940     (write _test-input-stream "fn foo {\n")
 9941     (write _test-input-stream "  var a: (array int 3)\n")
 9942     (write _test-input-stream "  var b/eax: int <- copy 0\n")
 9943     (write _test-input-stream "  var c/ecx: int <- copy 0\n")
 9944     (write _test-input-stream "  b, c <- length a\n")
 9945     (write _test-input-stream "}\n")
 9946     # convert
 9947     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9948     # registers except esp clobbered at this point
 9949     # restore ed
 9950     89/<- %edx 4/r32/esp
 9951     (flush _test-output-buffered-file)
 9952     (flush _test-error-buffered-file)
 9953 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9959     # check output
 9960     (check-stream-equal _test-output-stream  ""  "F - test-length-with-too-many-outputs: output should be empty")
 9961     (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")
 9962     # check that stop(1) was called
 9963     (check-ints-equal *(edx+4) 2 "F - test-length-with-too-many-outputs: exit status")
 9964     # don't restore from ebp
 9965     81 0/subop/add %esp 8/imm32
 9966     # . epilogue
 9967     5d/pop-to-ebp
 9968     c3/return
 9969 
 9970 test-convert-function-with-return-register-and-local:
 9971     # . prologue
 9972     55/push-ebp
 9973     89/<- %ebp 4/r32/esp
 9974     # setup
 9975     (clear-stream _test-input-stream)
 9976     (clear-stream $_test-input-buffered-file->buffer)
 9977     (clear-stream _test-output-stream)
 9978     (clear-stream $_test-output-buffered-file->buffer)
 9979     #
 9980     (write _test-input-stream "fn foo -> x/eax: int {\n")
 9981     (write _test-input-stream "  var y/eax: int <- copy 3\n")
 9982     (write _test-input-stream "  var z/ecx: int <- copy 4\n")
 9983     (write _test-input-stream "  return y\n")
 9984     (write _test-input-stream "}\n")
 9985     # convert
 9986     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 9987     (flush _test-output-buffered-file)
 9988 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9994     # check output
 9995     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-register-and-local/0")
 9996     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-register-and-local/1")
 9997     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-register-and-local/2")
 9998     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-register-and-local/3")
 9999     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-register-and-local/4")
10000     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-register-and-local/5")
10001     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-with-return-register-and-local/6")
10002     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 3/imm32"  "F - test-convert-function-with-return-register-and-local/7")
10003     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-return-register-and-local/8")
10004     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 4/imm32"  "F - test-convert-function-with-return-register-and-local/9")
10005     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32" "F - test-convert-function-with-return-register-and-local/10")
10006     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-function-with-return-register-and-local/11")
10007     (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")
10008     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-register-and-local/13")
10009     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-register-and-local/14")
10010     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-register-and-local/15")
10011     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-register-and-local/16")
10012     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-register-and-local/17")
10013     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-register-and-local/18")
10014     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-register-and-local/19")
10015     # . epilogue
10016     89/<- %esp 5/r32/ebp
10017     5d/pop-to-ebp
10018     c3/return
10019 
10020 test-convert-function-with-return-register-and-local-2:
10021     # . prologue
10022     55/push-ebp
10023     89/<- %ebp 4/r32/esp
10024     # setup
10025     (clear-stream _test-input-stream)
10026     (clear-stream $_test-input-buffered-file->buffer)
10027     (clear-stream _test-output-stream)
10028     (clear-stream $_test-output-buffered-file->buffer)
10029     #
10030     (write _test-input-stream "fn foo -> x/eax: int {\n")
10031     (write _test-input-stream "  var y/eax: int <- copy 3\n")
10032     (write _test-input-stream "  var z/ecx: int <- copy 4\n")
10033     (write _test-input-stream "  return z\n")
10034     (write _test-input-stream "}\n")
10035     # convert
10036     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
10037     (flush _test-output-buffered-file)
10038 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
10044     # check output
10045     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-register-and-local-2/0")
10046     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-register-and-local-2/1")
10047     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-register-and-local-2/2")
10048     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-register-and-local-2/3")
10049     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-register-and-local-2/4")
10050     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-register-and-local-2/5")
10051     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-with-return-register-and-local-2/6")
10052     (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")
10053     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-return-register-and-local-2/8")
10054     (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")
10055     (check-next-stream-line-equal _test-output-stream "    8b/-> %ecx 0x00000000/r32" "F - test-convert-function-with-return-register-and-local-2/10")
10056     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-function-with-return-register-and-local-2/11")
10057     (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")
10058     (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")
10059     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-register-and-local-2/14")
10060     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-register-and-local-2/15")
10061     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-register-and-local-2/16")
10062     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-register-and-local-2/17")
10063     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-register-and-local-2/18")
10064     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-register-and-local-2/19")
10065     # . epilogue
10066     89/<- %esp 5/r32/ebp
10067     5d/pop-to-ebp
10068     c3/return
10069 
10070 test-convert-function-with-return-float-register-and-local:
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     #
10080     (write _test-input-stream "fn foo -> f/xmm1: float {\n")
10081     (write _test-input-stream "  var y/eax: int <- copy 3\n")
10082     (write _test-input-stream "  var g/xmm0: float <- convert y\n")
10083     (write _test-input-stream "  var h/xmm1: float <- convert y\n")
10084     (write _test-input-stream "  return g\n")
10085     (write _test-input-stream "}\n")
10086     # convert
10087     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
10088     (flush _test-output-buffered-file)
10089 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
10095     # check output
10096     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-float-register-and-local/0")
10097     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-float-register-and-local/1")
10098     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-float-register-and-local/2")
10099     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-float-register-and-local/3")
10100     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-float-register-and-local/4")
10101     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-float-register-and-local/5")
10102     (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
10103     (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")
10104     (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
10105     (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")
10106     (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")
10107     (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
10108     (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")
10109     (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")
10110     (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
10111     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-floating-point-dereferenced/15")  # reclaim h
10112     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 0/x32"  "F - test-convert-floating-point-dereferenced/16")  # reclaim g
10113     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-floating-point-dereferenced/17")
10114     (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
10115     (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")
10116     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-float-register-and-local/20")
10117     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-float-register-and-local/21")
10118     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-float-register-and-local/22")
10119     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-float-register-and-local/23")
10120     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-float-register-and-local/24")
10121     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-float-register-and-local/25")
10122     # . epilogue
10123     89/<- %esp 5/r32/ebp
10124     5d/pop-to-ebp
10125     c3/return
10126 
10127 test-convert-function-with-return-and-local-vars:
10128     # . prologue
10129     55/push-ebp
10130     89/<- %ebp 4/r32/esp
10131     # setup
10132     (clear-stream _test-input-stream)
10133     (clear-stream $_test-input-buffered-file->buffer)
10134     (clear-stream _test-output-stream)
10135     (clear-stream $_test-output-buffered-file->buffer)
10136     #
10137     (write _test-input-stream "fn foo -> a/eax: int {\n")
10138     (write _test-input-stream "  {\n")
10139     (write _test-input-stream "    var x: int\n")
10140     (write _test-input-stream "    {\n")
10141     (write _test-input-stream "      var y: int\n")
10142     (write _test-input-stream "      return y\n")
10143     (write _test-input-stream "      increment x\n")
10144     (write _test-input-stream "    }\n")
10145     (write _test-input-stream "  }\n")
10146     (write _test-input-stream "}\n")
10147     # convert
10148     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
10149     (flush _test-output-buffered-file)
10150 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
10156     # check output
10157     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-and-local-vars/0")
10158     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-and-local-vars/1")
10159     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-and-local-vars/2")
10160     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-and-local-vars/3")
10161     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-and-local-vars/4")
10162     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-and-local-vars/5")
10163     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-return-and-local-vars/6")
10164     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-return-and-local-vars/7")
10165     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-return-and-local-vars/8")  # var x
10166     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-return-and-local-vars/9")
10167     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-return-and-local-vars/10")
10168     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-return-and-local-vars/11")  # var y
10169     (check-next-stream-line-equal _test-output-stream "        8b/-> *(ebp+0xfffffff8) 0x00000000/r32" "F - test-convert-function-with-return-and-local-vars/12")
10170     (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")
10171     (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")
10172     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-and-local-vars/15")
10173     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-return-and-local-vars/16")
10174     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-return-and-local-vars/17")
10175     (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")
10176     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-return-and-local-vars/19")
10177     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-return-and-local-vars/20")
10178     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-and-local-vars/21")
10179     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-and-local-vars/22")
10180     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-and-local-vars/23")
10181     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-and-local-vars/24")
10182     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-and-local-vars/25")
10183     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-and-local-vars/26")
10184     # . epilogue
10185     89/<- %esp 5/r32/ebp
10186     5d/pop-to-ebp
10187     c3/return
10188 
10189 #######################################################
10190 # Parsing
10191 #######################################################
10192 
10193 == data
10194 
10195 # Global state added to each var record when parsing a function
10196 Next-block-index:  # (addr int)
10197     1/imm32
10198 
10199 Curr-block-depth:  # (addr int)
10200     1/imm32
10201 
10202 == code
10203 
10204 parse-mu:  # in: (addr buffered-file), err: (addr buffered-file), ed: (addr exit-descriptor)
10205     # pseudocode
10206     #   var curr-function: (addr handle function) = Program->functions
10207     #   var curr-signature: (addr handle function) = Program->signatures
10208     #   var curr-type: (addr handle typeinfo) = Program->types
10209     #   var line: (stream byte 512)
10210     #   var word-slice: slice
10211     #   while true                                  # line loop
10212     #     clear-stream(line)
10213     #     read-line-buffered(in, line)
10214     #     if (line->write == 0) break               # end of file
10215     #     word-slice = next-mu-token(line)
10216     #     if slice-empty?(word-slice)               # end of line
10217     #       continue
10218     #     else if slice-starts-with?(word-slice, "#")  # comment
10219     #       continue                                # end of line
10220     #     else if slice-equal?(word-slice, "fn")
10221     #       var new-function: (handle function) = allocate(function)
10222     #       var vars: (stack live-var 256)
10223     #       populate-mu-function-header(line, new-function, vars)
10224     #       populate-mu-function-body(in, new-function, vars)
10225     #       assert(vars->top == 0)
10226     #       *curr-function = new-function
10227     #       curr-function = &new-function->next
10228     #     else if slice-equal?(word-slice, "sig")
10229     #       var new-function: (handle function) = allocate(function)
10230     #       populate-mu-function-signature(line, new-function)
10231     #       *curr-signature = new-function
10232     #       curr-signature = &new-function->next
10233     #     else if slice-equal?(word-slice, "type")
10234     #       word-slice = next-mu-token(line)
10235     #       type-id = pos-or-insert-slice(Type-id, word-slice)
10236     #       var new-type: (handle typeinfo) = find-or-create-typeinfo(type-id)
10237     #       assert(next-word(line) == "{")
10238     #       populate-mu-type(in, new-type)
10239     #     else
10240     #       abort()
10241     #
10242     # . prologue
10243     55/push-ebp
10244     89/<- %ebp 4/r32/esp
10245     # var curr-signature: (addr handle function) at *(ebp-4)
10246     68/push _Program-signatures/imm32
10247     # . save registers
10248     50/push-eax
10249     51/push-ecx
10250     52/push-edx
10251     53/push-ebx
10252     56/push-esi
10253     57/push-edi
10254     # var line/ecx: (stream byte 512)
10255     81 5/subop/subtract %esp 0x200/imm32
10256     68/push 0x200/imm32/size
10257     68/push 0/imm32/read
10258     68/push 0/imm32/write
10259     89/<- %ecx 4/r32/esp
10260     # var word-slice/edx: slice
10261     68/push 0/imm32/end
10262     68/push 0/imm32/start
10263     89/<- %edx 4/r32/esp
10264     # var curr-function/edi: (addr handle function)
10265     bf/copy-to-edi _Program-functions/imm32
10266     # var vars/ebx: (stack live-var 256)
10267     81 5/subop/subtract %esp 0xc00/imm32
10268     68/push 0xc00/imm32/size
10269     68/push 0/imm32/top
10270     89/<- %ebx 4/r32/esp
10271     {
10272 $parse-mu:line-loop:
10273       (clear-stream %ecx)
10274       (read-line-buffered *(ebp+8) %ecx)
10275       # if (line->write == 0) break
10276       81 7/subop/compare *ecx 0/imm32
10277       0f 84/jump-if-= break/disp32
10278 +--  6 lines: #?       # dump line ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
10284       (next-mu-token %ecx %edx)
10285       # if slice-empty?(word-slice) continue
10286       (slice-empty? %edx)  # => eax
10287       3d/compare-eax-and 0/imm32/false
10288       0f 85/jump-if-!= loop/disp32
10289       # if (*word-slice->start == "#") continue
10290       # . eax = *word-slice->start
10291       8b/-> *edx 0/r32/eax
10292       8a/copy-byte *eax 0/r32/AL
10293       81 4/subop/and %eax 0xff/imm32
10294       # . if (eax == '#') continue
10295       3d/compare-eax-and 0x23/imm32/hash
10296       0f 84/jump-if-= loop/disp32
10297       # if (slice-equal?(word-slice, "fn")) parse a function
10298       {
10299 $parse-mu:fn:
10300         (slice-equal? %edx "fn")  # => eax
10301         3d/compare-eax-and 0/imm32/false
10302         0f 84/jump-if-= break/disp32
10303         # var new-function/esi: (handle function)
10304         68/push 0/imm32
10305         68/push 0/imm32
10306         89/<- %esi 4/r32/esp
10307         # populate-mu-function(line, in, vars, new-function)
10308         (allocate Heap *Function-size %esi)
10309         # var new-function-addr/eax: (addr function)
10310         (lookup *esi *(esi+4))  # => eax
10311         # initialize vars
10312         (clear-stack %ebx)
10313         #
10314         (populate-mu-function-header %ecx %eax %ebx *(ebp+0xc) *(ebp+0x10))
10315         (populate-mu-function-body *(ebp+8) %eax %ebx *(ebp+0xc) *(ebp+0x10))
10316         # *curr-function = new-function
10317         8b/-> *esi 0/r32/eax
10318         89/<- *edi 0/r32/eax
10319         8b/-> *(esi+4) 0/r32/eax
10320         89/<- *(edi+4) 0/r32/eax
10321         # curr-function = &new-function->next
10322         # . var tmp/eax: (addr function) = lookup(new-function)
10323         (lookup *esi *(esi+4))  # => eax
10324         # . curr-function = &tmp->next
10325         8d/copy-address *(eax+0x20) 7/r32/edi  # Function-next
10326         # reclaim new-function
10327         81 0/subop/add %esp 8/imm32
10328         #
10329         e9/jump $parse-mu:line-loop/disp32
10330       }
10331       # if (slice-equal?(word-slice, "sig")) parse a function signature
10332       # Function signatures are for providing types to SubX functions.
10333       {
10334 $parse-mu:sig:
10335         (slice-equal? %edx "sig")  # => eax
10336         3d/compare-eax-and 0/imm32/false
10337         0f 84/jump-if-= break/disp32
10338         # edi = curr-function
10339         57/push-edi
10340         8b/-> *(ebp-4) 7/r32/edi
10341         # var new-function/esi: (handle function)
10342         68/push 0/imm32
10343         68/push 0/imm32
10344         89/<- %esi 4/r32/esp
10345         # populate-mu-function(line, in, vars, new-function)
10346         (allocate Heap *Function-size %esi)
10347         # var new-function-addr/eax: (addr function)
10348         (lookup *esi *(esi+4))  # => eax
10349         #
10350         (populate-mu-function-signature %ecx %eax *(ebp+0xc) *(ebp+0x10))
10351         # *curr-signature = new-function
10352         8b/-> *esi 0/r32/eax
10353         89/<- *edi 0/r32/eax
10354         8b/-> *(esi+4) 0/r32/eax
10355         89/<- *(edi+4) 0/r32/eax
10356         # curr-signature = &new-function->next
10357         # . var tmp/eax: (addr function) = lookup(new-function)
10358         (lookup *esi *(esi+4))  # => eax
10359         # . curr-function = &tmp->next
10360         8d/copy-address *(eax+0x20) 7/r32/edi  # Function-next
10361         # reclaim new-function
10362         81 0/subop/add %esp 8/imm32
10363         # save curr-function
10364         89/<- *(ebp-4) 7/r32/edi
10365         # restore edi
10366         5f/pop-to-edi
10367         #
10368         e9/jump $parse-mu:line-loop/disp32
10369       }
10370       # if (slice-equal?(word-slice, "type")) parse a type (struct/record) definition
10371       {
10372 $parse-mu:type:
10373         (slice-equal? %edx "type")  # => eax
10374         3d/compare-eax-and 0/imm32
10375         0f 84/jump-if-= break/disp32
10376         (next-mu-token %ecx %edx)
10377         # var type-id/eax: int
10378         (pos-or-insert-slice Type-id %edx)  # => eax
10379         # spill
10380         51/push-ecx
10381         # var new-type/ecx: (handle typeinfo)
10382         68/push 0/imm32
10383         68/push 0/imm32
10384         89/<- %ecx 4/r32/esp
10385         (find-or-create-typeinfo %eax %ecx)
10386         #
10387         (lookup *ecx *(ecx+4))  # => eax
10388         # TODO: ensure that 'line' has nothing else but '{'
10389 #? (dump-typeinfos "=== aaa\n")
10390         (populate-mu-type *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10))  # => eax
10391 #? (dump-typeinfos "=== zzz\n")
10392         # reclaim new-type
10393         81 0/subop/add %esp 8/imm32
10394         # restore
10395         59/pop-to-ecx
10396         e9/jump $parse-mu:line-loop/disp32
10397       }
10398       # otherwise abort
10399       e9/jump $parse-mu:error1/disp32
10400     } # end line loop
10401 $parse-mu:end:
10402     # . reclaim locals
10403     81 0/subop/add %esp 0x20c/imm32  # line
10404     81 0/subop/add %esp 0xc08/imm32  # vars
10405     81 0/subop/add %esp 8/imm32
10406     # . restore registers
10407     5f/pop-to-edi
10408     5e/pop-to-esi
10409     5b/pop-to-ebx
10410     5a/pop-to-edx
10411     59/pop-to-ecx
10412     58/pop-to-eax
10413     # . reclaim local
10414     81 0/subop/add %esp 4/imm32
10415     # . epilogue
10416     89/<- %esp 5/r32/ebp
10417     5d/pop-to-ebp
10418     c3/return
10419 
10420 $parse-mu:error1:
10421     # error("unexpected top-level command: " word-slice "\n")
10422     (write-buffered *(ebp+0xc) "unexpected top-level command: ")
10423     (write-slice-buffered *(ebp+0xc) %edx)
10424     (write-buffered *(ebp+0xc) "\n")
10425     (flush *(ebp+0xc))
10426     (stop *(ebp+0x10) 1)
10427     # never gets here
10428 
10429 $parse-mu:error2:
10430     # error(vars->top " vars not reclaimed after fn '" new-function->name "'\n")
10431     (write-int32-hex-buffered *(ebp+0xc) *ebx)
10432     (write-buffered *(ebp+0xc) " vars not reclaimed after fn '")
10433     (write-slice-buffered *(ebp+0xc) *eax)  # Function-name
10434     (write-buffered *(ebp+0xc) "'\n")
10435     (flush *(ebp+0xc))
10436     (stop *(ebp+0x10) 1)
10437     # never gets here
10438 
10439 # scenarios considered:
10440 # ✗ fn foo  # no block
10441 # ✓ fn foo {
10442 # ✗ fn foo { {
10443 # ✗ fn foo { }
10444 # ✗ fn foo { } {
10445 # ✗ fn foo x {
10446 # ✗ fn foo x: {
10447 # ✓ fn foo x: int {
10448 # ✓ fn foo x: int {
10449 # ✓ fn foo x: int -> y/eax: int {
10450 # TODO:
10451 #   disallow outputs of type `(... addr ...)`
10452 #   disallow inputs of type `(... addr ... addr ...)`
10453 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)
10454     # pseudocode:
10455     #   var word-slice: slice
10456     #   next-mu-token(first-line, word-slice)
10457     #   if slice-empty?(word-slice) abort
10458     #   assert(word-slice not in '{' '}' '->')
10459     #   out->name = slice-to-string(word-slice)
10460     #   ## inouts
10461     #   while true
10462     #     word-slice = next-mu-token(first-line)
10463     #     if slice-empty?(word-slice) abort
10464     #     if (word-slice == '{') goto done
10465     #     if (word-slice == '->') break
10466     #     assert(word-slice != '}')
10467     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
10468     #     assert(v->register == null)
10469     #     # v->block-depth is implicitly 0
10470     #     out->inouts = append(v, out->inouts)
10471     #     push(vars, {v, false})
10472     #   ## outputs
10473     #   while true
10474     #     word-slice = next-mu-token(first-line)
10475     #     if slice-empty?(word-slice) abort
10476     #     if (word-slice == '{') break
10477     #     assert(word-slice not in '}' '->')
10478     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
10479     #     assert(v->register != null)
10480     #     out->outputs = append(v, out->outputs)
10481     #   done:
10482     #
10483     # . prologue
10484     55/push-ebp
10485     89/<- %ebp 4/r32/esp
10486     # . save registers
10487     50/push-eax
10488     51/push-ecx
10489     52/push-edx
10490     53/push-ebx
10491     57/push-edi
10492     # edi = out
10493     8b/-> *(ebp+0xc) 7/r32/edi
10494     # var word-slice/ecx: slice
10495     68/push 0/imm32/end
10496     68/push 0/imm32/start
10497     89/<- %ecx 4/r32/esp
10498     # var v/ebx: (handle var)
10499     68/push 0/imm32
10500     68/push 0/imm32
10501     89/<- %ebx 4/r32/esp
10502     # read function name
10503     (next-mu-token *(ebp+8) %ecx)
10504     # error checking
10505     # if slice-empty?(word-slice) abort
10506     (slice-empty? %ecx)  # => eax
10507     3d/compare-eax-and 0/imm32/false
10508     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
10509     # if (word-slice == '{') abort
10510     (slice-equal? %ecx "{")   # => eax
10511     3d/compare-eax-and 0/imm32/false
10512     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
10513     # if (word-slice == '->') abort
10514     (slice-equal? %ecx "->")   # => eax
10515     3d/compare-eax-and 0/imm32/false
10516     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
10517     # if (word-slice == '}') abort
10518     (slice-equal? %ecx "}")   # => eax
10519     3d/compare-eax-and 0/imm32/false
10520     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
10521     # save function name
10522     (slice-to-string Heap %ecx %edi)  # Function-name
10523     # save function inouts
10524     {
10525 $populate-mu-function-header:check-for-inout:
10526       (next-mu-token *(ebp+8) %ecx)
10527       # if slice-empty?(word-slice) abort
10528       (slice-empty? %ecx)  # => eax
10529       3d/compare-eax-and 0/imm32/false
10530       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
10531       # if (word-slice == '{') goto done
10532       (slice-equal? %ecx "{")   # => eax
10533       3d/compare-eax-and 0/imm32/false
10534       0f 85/jump-if-!= $populate-mu-function-header:done/disp32
10535       # if (word-slice == '->') break
10536       (slice-equal? %ecx "->")   # => eax
10537       3d/compare-eax-and 0/imm32/false
10538       0f 85/jump-if-!= break/disp32
10539       # if (word-slice == '}') abort
10540       (slice-equal? %ecx "}")   # => eax
10541       3d/compare-eax-and 0/imm32/false
10542       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
10543       # v = parse-var-with-type(word-slice, first-line)
10544       (parse-var-with-type %ecx *(ebp+8) %ebx *(ebp+0x14) *(ebp+0x18))
10545       # assert(v->register == null)
10546       # . eax: (addr var) = lookup(v)
10547       (lookup *ebx *(ebx+4))  # => eax
10548       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
10549       0f 85/jump-if-!= $populate-mu-function-header:error2/disp32
10550       # v->block-depth is implicitly 0
10551       #
10552       # out->inouts = append(v, out->inouts)
10553       8d/copy-address *(edi+8) 0/r32/eax  # Function-inouts
10554       (append-list Heap  *ebx *(ebx+4)  *(edi+8) *(edi+0xc)  %eax)  # Function-inouts, Function-inouts
10555       # push(vars, {v, false})
10556       (push *(ebp+0x10) *ebx)
10557       (push *(ebp+0x10) *(ebx+4))
10558       (push *(ebp+0x10) 0)  # false
10559       #
10560       e9/jump loop/disp32
10561     }
10562     # save function outputs
10563     {
10564 $populate-mu-function-header:check-for-out:
10565       (next-mu-token *(ebp+8) %ecx)
10566       # if slice-empty?(word-slice) abort
10567       (slice-empty? %ecx)  # => eax
10568       3d/compare-eax-and 0/imm32/false
10569       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
10570       # if (word-slice == '{') break
10571       (slice-equal? %ecx "{")   # => eax
10572       3d/compare-eax-and 0/imm32/false
10573       0f 85/jump-if-!= break/disp32
10574       # if (word-slice == '->') abort
10575       (slice-equal? %ecx "->")   # => eax
10576       3d/compare-eax-and 0/imm32/false
10577       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
10578       # if (word-slice == '}') abort
10579       (slice-equal? %ecx "}")   # => eax
10580       3d/compare-eax-and 0/imm32/false
10581       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
10582       # v = parse-var-with-type(word-slice, first-line)
10583       (parse-var-with-type %ecx *(ebp+8) %ebx *(ebp+0x14) *(ebp+0x18))
10584       # assert(var->register != null)
10585       # . eax: (addr var) = lookup(v)
10586       (lookup *ebx *(ebx+4))  # => eax
10587       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
10588       0f 84/jump-if-= $populate-mu-function-header:error3/disp32
10589       # out->outputs = append(v, out->outputs)
10590       8d/copy-address *(edi+0x10) 0/r32/eax  # Function-outputs
10591       (append-list Heap  *ebx *(ebx+4)  *(edi+0x10) *(edi+0x14)  %eax)  # Function-outputs, Function-outputs
10592       #
10593       e9/jump loop/disp32
10594     }
10595 $populate-mu-function-header:done:
10596     (check-no-tokens-left *(ebp+8))
10597 $populate-mu-function-header:end:
10598     # . reclaim locals
10599     81 0/subop/add %esp 0x10/imm32
10600     # . restore registers
10601     5f/pop-to-edi
10602     5b/pop-to-ebx
10603     5a/pop-to-edx
10604     59/pop-to-ecx
10605     58/pop-to-eax
10606     # . epilogue
10607     89/<- %esp 5/r32/ebp
10608     5d/pop-to-ebp
10609     c3/return
10610 
10611 $populate-mu-function-header:error1:
10612     # error("function header not in form 'fn <name> {'")
10613     (write-buffered *(ebp+0x14) "function header not in form 'fn <name> [inouts] [-> outputs] {' -- '")
10614     (flush *(ebp+0x14))
10615     (rewind-stream *(ebp+8))
10616     (write-stream-data *(ebp+0x14) *(ebp+8))
10617     (write-buffered *(ebp+0x14) "'\n")
10618     (flush *(ebp+0x14))
10619     (stop *(ebp+0x18) 1)
10620     # never gets here
10621 
10622 $populate-mu-function-header:error2:
10623     # error("fn " fn ": function inout '" var "' cannot be in a register")
10624     (write-buffered *(ebp+0x14) "fn ")
10625     50/push-eax
10626     (lookup *edi *(edi+4))  # Function-name Function-name => eax
10627     (write-buffered *(ebp+0x14) %eax)
10628     58/pop-to-eax
10629     (write-buffered *(ebp+0x14) ": function inout '")
10630     (lookup *eax *(eax+4))  # Var-name Var-name => eax
10631     (write-buffered *(ebp+0x10) %eax)
10632     (write-buffered *(ebp+0x14) "' cannot be in a register")
10633     (flush *(ebp+0x14))
10634     (stop *(ebp+0x18) 1)
10635     # never gets here
10636 
10637 $populate-mu-function-header:error3:
10638     # error("fn " fn ": function output '" var "' must be in a register")
10639     (write-buffered *(ebp+0x14) "fn ")
10640     50/push-eax
10641     (lookup *edi *(edi+4))  # Function-name Function-name => eax
10642     (write-buffered *(ebp+0x14) %eax)
10643     58/pop-to-eax
10644     (write-buffered *(ebp+0x14) ": function output '")
10645     (lookup *ebx *(ebx+4))  # => eax
10646     (lookup *eax *(eax+4))  # Var-name Var-name => eax
10647     (write-buffered *(ebp+0x14) %eax)
10648     (write-buffered *(ebp+0x14) "' must be in a register, in instruction '")
10649     (rewind-stream *(ebp+8))
10650     (write-stream-data *(ebp+0x14) *(ebp+8))
10651     (write-buffered *(ebp+0x14) "'\n")
10652     (flush *(ebp+0x14))
10653     (stop *(ebp+0x18) 1)
10654     # never gets here
10655 
10656 # scenarios considered:
10657 # ✓ fn foo
10658 # ✗ fn foo {
10659 # ✓ fn foo x
10660 # ✓ fn foo x: int
10661 # ✓ fn foo x: int -> y/eax: int
10662 # TODO:
10663 #   disallow outputs of type `(... addr ...)`
10664 #   disallow inputs of type `(... addr ... addr ...)`
10665 populate-mu-function-signature:  # first-line: (addr stream byte), out: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
10666     # pseudocode:
10667     #   var word-slice: slice
10668     #   next-mu-token(first-line, word-slice)
10669     #   assert(word-slice not in '{' '}' '->')
10670     #   out->name = slice-to-string(word-slice)
10671     #   ## inouts
10672     #   while true
10673     #     word-slice = next-mu-token(first-line)
10674     #     if slice-empty?(word-slice) break
10675     #     if (word-slice == '->') break
10676     #     assert(word-slice not in '{' '}')
10677     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
10678     #     assert(v->register == null)
10679     #     # v->block-depth is implicitly 0
10680     #     out->inouts = append(v, out->inouts)
10681     #   ## outputs
10682     #   while true
10683     #     word-slice = next-mu-token(first-line)
10684     #     if slice-empty?(word-slice) break
10685     #     assert(word-slice not in '{' '}' '->')
10686     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
10687     #     assert(v->register != null)
10688     #     out->outputs = append(v, out->outputs)
10689     #
10690     # . prologue
10691     55/push-ebp
10692     89/<- %ebp 4/r32/esp
10693     # . save registers
10694     50/push-eax
10695     51/push-ecx
10696     52/push-edx
10697     53/push-ebx
10698     57/push-edi
10699     # edi = out
10700     8b/-> *(ebp+0xc) 7/r32/edi
10701     # var word-slice/ecx: slice
10702     68/push 0/imm32/end
10703     68/push 0/imm32/start
10704     89/<- %ecx 4/r32/esp
10705     # var v/ebx: (handle var)
10706     68/push 0/imm32
10707     68/push 0/imm32
10708     89/<- %ebx 4/r32/esp
10709     # read function name
10710     (next-mu-token *(ebp+8) %ecx)
10711     # error checking
10712     # if (word-slice == '{') abort
10713     (slice-equal? %ecx "{")   # => eax
10714     3d/compare-eax-and 0/imm32/false
10715     0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
10716     # if (word-slice == '->') abort
10717     (slice-equal? %ecx "->")   # => eax
10718     3d/compare-eax-and 0/imm32/false
10719     0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
10720     # if (word-slice == '}') abort
10721     (slice-equal? %ecx "}")   # => eax
10722     3d/compare-eax-and 0/imm32/false
10723     0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
10724     # save function name
10725     (slice-to-string Heap %ecx %edi)  # Function-name
10726     # save function inouts
10727     {
10728 $populate-mu-function-signature:check-for-inout:
10729       (next-mu-token *(ebp+8) %ecx)
10730       (slice-empty? %ecx)  # => eax
10731       3d/compare-eax-and 0/imm32/false
10732       0f 85/jump-if-!= break/disp32
10733       # if (word-slice == '->') break
10734       (slice-equal? %ecx "->")   # => eax
10735       3d/compare-eax-and 0/imm32/false
10736       0f 85/jump-if-!= break/disp32
10737       # if (word-slice == '{') abort
10738       (slice-equal? %ecx "{")   # => eax
10739       3d/compare-eax-and 0/imm32/false
10740       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
10741       # if (word-slice == '}') abort
10742       (slice-equal? %ecx "}")   # => eax
10743       3d/compare-eax-and 0/imm32/false
10744       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
10745       # v = parse-var-with-type(word-slice, first-line)
10746       (parse-var-with-type %ecx *(ebp+8) %ebx *(ebp+0x10) *(ebp+0x14))
10747       # assert(v->register == null)
10748       # . eax: (addr var) = lookup(v)
10749       (lookup *ebx *(ebx+4))  # => eax
10750       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
10751       0f 85/jump-if-!= $populate-mu-function-signature:error2/disp32
10752       # v->block-depth is implicitly 0
10753       #
10754       # out->inouts = append(v, out->inouts)
10755       8d/copy-address *(edi+8) 0/r32/eax  # Function-inouts
10756       (append-list Heap  *ebx *(ebx+4)  *(edi+8) *(edi+0xc)  %eax)  # Function-inouts, Function-inouts
10757       #
10758       e9/jump loop/disp32
10759     }
10760     # save function outputs
10761     {
10762 $populate-mu-function-signature:check-for-out:
10763       (next-mu-token *(ebp+8) %ecx)
10764       (slice-empty? %ecx)  # => eax
10765       3d/compare-eax-and 0/imm32/false
10766       0f 85/jump-if-!= break/disp32
10767       # if (word-slice == '{') abort
10768       (slice-equal? %ecx "{")   # => eax
10769       3d/compare-eax-and 0/imm32/false
10770       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
10771       # if (word-slice == '->') abort
10772       (slice-equal? %ecx "->")   # => eax
10773       3d/compare-eax-and 0/imm32/false
10774       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
10775       # if (word-slice == '}') abort
10776       (slice-equal? %ecx "}")   # => eax
10777       3d/compare-eax-and 0/imm32/false
10778       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
10779       # v = parse-var-with-type(word-slice, first-line)
10780       (parse-var-with-type %ecx *(ebp+8) %ebx *(ebp+0x10) *(ebp+0x14))
10781       # assert(var->register != null)
10782       # . eax: (addr var) = lookup(v)
10783       (lookup *ebx *(ebx+4))  # => eax
10784       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
10785       0f 84/jump-if-= $populate-mu-function-signature:error3/disp32
10786       # out->outputs = append(v, out->outputs)
10787       8d/copy-address *(edi+0x10) 0/r32/eax  # Function-outputs
10788       (append-list Heap  *ebx *(ebx+4)  *(edi+0x10) *(edi+0x14)  %eax)  # Function-outputs, Function-outputs
10789       #
10790       e9/jump loop/disp32
10791     }
10792 $populate-mu-function-signature:done:
10793     (check-no-tokens-left *(ebp+8))
10794 $populate-mu-function-signature:end:
10795     # . reclaim locals
10796     81 0/subop/add %esp 0x10/imm32
10797     # . restore registers
10798     5f/pop-to-edi
10799     5b/pop-to-ebx
10800     5a/pop-to-edx
10801     59/pop-to-ecx
10802     58/pop-to-eax
10803     # . epilogue
10804     89/<- %esp 5/r32/ebp
10805     5d/pop-to-ebp
10806     c3/return
10807 
10808 $populate-mu-function-signature:error1:
10809     # error("function signature not in form 'fn <name> {'")
10810     (write-buffered *(ebp+0x10) "function signature not in form 'fn <name> [inouts] [-> outputs] {' -- '")
10811     (flush *(ebp+0x10))
10812     (rewind-stream *(ebp+8))
10813     (write-stream-data *(ebp+0x10) *(ebp+8))
10814     (write-buffered *(ebp+0x10) "'\n")
10815     (flush *(ebp+0x10))
10816     (stop *(ebp+0x14) 1)
10817     # never gets here
10818 
10819 $populate-mu-function-signature:error2:
10820     # error("fn " fn ": function inout '" var "' cannot be in a register")
10821     (write-buffered *(ebp+0x10) "fn ")
10822     50/push-eax
10823     (lookup *edi *(edi+4))  # Function-name Function-name => eax
10824     (write-buffered *(ebp+0x10) %eax)
10825     58/pop-to-eax
10826     (write-buffered *(ebp+0x10) ": function inout '")
10827     (lookup *eax *(eax+4))  # Var-name Var-name => eax
10828     (write-buffered *(ebp+0x10) %eax)
10829     (write-buffered *(ebp+0x10) "' cannot be in a register")
10830     (flush *(ebp+0x10))
10831     (stop *(ebp+0x14) 1)
10832     # never gets here
10833 
10834 $populate-mu-function-signature:error3:
10835     # error("fn " fn ": function output '" var "' must be in a register")
10836     (write-buffered *(ebp+0x10) "fn ")
10837     50/push-eax
10838     (lookup *edi *(edi+4))  # Function-name Function-name => eax
10839     (write-buffered *(ebp+0x10) %eax)
10840     58/pop-to-eax
10841     (write-buffered *(ebp+0x10) ": function output '")
10842     (lookup *ebx *(ebx+4))  # => eax
10843     (lookup *eax *(eax+4))  # Var-name Var-name => eax
10844     (write-buffered *(ebp+0x10) %eax)
10845     (write-buffered *(ebp+0x10) "' must be in a register, in instruction '")
10846     (rewind-stream *(ebp+8))
10847     (write-stream-data *(ebp+0x10) *(ebp+8))
10848     (write-buffered *(ebp+0x10) "'\n")
10849     (flush *(ebp+0x10))
10850     (stop *(ebp+0x14) 1)
10851     # never gets here
10852 
10853 test-function-header-with-arg:
10854     # . prologue
10855     55/push-ebp
10856     89/<- %ebp 4/r32/esp
10857     # setup
10858     8b/-> *Primitive-type-ids 0/r32/eax
10859     89/<- *Type-id 0/r32/eax  # stream-write
10860     (clear-stream _test-input-stream)
10861     (write _test-input-stream "foo n: int {\n")
10862     # var result/ecx: function
10863     2b/subtract *Function-size 4/r32/esp
10864     89/<- %ecx 4/r32/esp
10865     (zero-out %ecx *Function-size)
10866     # var vars/ebx: (stack live-var 16)
10867     81 5/subop/subtract %esp 0xc0/imm32
10868     68/push 0xc0/imm32/size
10869     68/push 0/imm32/top
10870     89/<- %ebx 4/r32/esp
10871     # convert
10872     (populate-mu-function-header _test-input-stream %ecx %ebx Stderr 0)
10873     # check result->name
10874     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
10875     (check-strings-equal %eax "foo" "F - test-function-header-with-arg/name")
10876     # var v/edx: (addr var) = result->inouts->value
10877     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
10878     (lookup *eax *(eax+4))  # List-value List-value => eax
10879     89/<- %edx 0/r32/eax
10880     # check v->name
10881     (lookup *edx *(edx+4))  # Var-name Var-name => eax
10882     (check-strings-equal %eax "n" "F - test-function-header-with-arg/inout:0")
10883     # check v->type
10884     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
10885     (check-ints-equal *eax 1 "F - test-function-header-with-arg/inout:0/type:0")  # Type-tree-is-atom
10886     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-arg/inout:0/type:1")  # Type-tree-value
10887     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-arg/inout:0/type:2")  # Type-tree-right
10888     # . epilogue
10889     89/<- %esp 5/r32/ebp
10890     5d/pop-to-ebp
10891     c3/return
10892 
10893 test-function-header-with-multiple-args:
10894     # . prologue
10895     55/push-ebp
10896     89/<- %ebp 4/r32/esp
10897     # setup
10898     8b/-> *Primitive-type-ids 0/r32/eax
10899     89/<- *Type-id 0/r32/eax  # stream-write
10900     (clear-stream _test-input-stream)
10901     (write _test-input-stream "foo a: int, b: int c: int {\n")
10902     # result/ecx: function
10903     2b/subtract *Function-size 4/r32/esp
10904     89/<- %ecx 4/r32/esp
10905     (zero-out %ecx *Function-size)
10906     # var vars/ebx: (stack live-var 16)
10907     81 5/subop/subtract %esp 0xc0/imm32
10908     68/push 0xc0/imm32/size
10909     68/push 0/imm32/top
10910     89/<- %ebx 4/r32/esp
10911     # convert
10912     (populate-mu-function-header _test-input-stream %ecx %ebx Stderr 0)
10913     # check result->name
10914     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
10915     (check-strings-equal %eax "foo" "F - test-function-header-with-multiple-args/name")
10916     # var inouts/edx: (addr list var) = lookup(result->inouts)
10917     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
10918     89/<- %edx 0/r32/eax
10919 $test-function-header-with-multiple-args:inout0:
10920     # var v/ebx: (addr var) = lookup(inouts->value)
10921     (lookup *edx *(edx+4))  # List-value List-value => eax
10922     89/<- %ebx 0/r32/eax
10923     # check v->name
10924     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
10925     (check-strings-equal %eax "a" "F - test-function-header-with-multiple-args/inout:0")  # Var-name
10926     # check v->type
10927     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
10928     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args/inout:0/type:0")  # Type-tree-is-atom
10929     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args/inout:0/type:1")  # Type-tree-value
10930     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args/inout:0/type:2")  # Type-tree-right
10931 $test-function-header-with-multiple-args:inout1:
10932     # inouts = lookup(inouts->next)
10933     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
10934     89/<- %edx 0/r32/eax
10935     # v = lookup(inouts->value)
10936     (lookup *edx *(edx+4))  # List-value List-value => eax
10937     89/<- %ebx 0/r32/eax
10938     # check v->name
10939     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
10940     (check-strings-equal %eax "b" "F - test-function-header-with-multiple-args/inout:1")  # Var-name
10941     # check v->type
10942     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
10943     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args/inout:1/type:0")  # Type-tree-is-atom
10944     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args/inout:1/type:1")  # Type-tree-value
10945     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args/inout:1/type:2")  # Type-tree-right
10946 $test-function-header-with-multiple-args:inout2:
10947     # inouts = lookup(inouts->next)
10948     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
10949     89/<- %edx 0/r32/eax
10950     # v = lookup(inouts->value)
10951     (lookup *edx *(edx+4))  # List-value List-value => eax
10952     89/<- %ebx 0/r32/eax
10953     # check v->name
10954     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
10955     (check-strings-equal %eax "c" "F - test-function-header-with-multiple-args/inout:2")  # Var-name
10956     # check v->type
10957     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
10958     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args/inout:2/type:0")  # Type-tree-is-atom
10959     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args/inout:2/type:1")  # Type-tree-value
10960     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args/inout:2/type:2")  # Type-tree-right
10961     # . epilogue
10962     89/<- %esp 5/r32/ebp
10963     5d/pop-to-ebp
10964     c3/return
10965 
10966 test-function-header-with-multiple-args-and-outputs:
10967     # . prologue
10968     55/push-ebp
10969     89/<- %ebp 4/r32/esp
10970     # setup
10971     8b/-> *Primitive-type-ids 0/r32/eax
10972     89/<- *Type-id 0/r32/eax  # stream-write
10973     (clear-stream _test-input-stream)
10974     (write _test-input-stream "foo a: int, b: int, c: int -> x/ecx: int y/edx: int {\n")
10975     # result/ecx: function
10976     2b/subtract *Function-size 4/r32/esp
10977     89/<- %ecx 4/r32/esp
10978     (zero-out %ecx *Function-size)
10979     # var vars/ebx: (stack live-var 16)
10980     81 5/subop/subtract %esp 0xc0/imm32
10981     68/push 0xc0/imm32/size
10982     68/push 0/imm32/top
10983     89/<- %ebx 4/r32/esp
10984     # convert
10985     (populate-mu-function-header _test-input-stream %ecx %ebx Stderr 0)
10986     # check result->name
10987     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
10988     (check-strings-equal %eax "foo" "F - test-function-header-with-multiple-args-and-outputs/name")
10989     # var inouts/edx: (addr list var) = lookup(result->inouts)
10990     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
10991     89/<- %edx 0/r32/eax
10992 $test-function-header-with-multiple-args-and-outputs:inout0:
10993     # var v/ebx: (addr var) = lookup(inouts->value)
10994     (lookup *edx *(edx+4))  # List-value List-value => eax
10995     89/<- %ebx 0/r32/eax
10996     # check v->name
10997     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
10998     (check-strings-equal %eax "a" "F - test-function-header-with-multiple-args-and-outputs/inout:0")
10999     # check v->type
11000     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
11001     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:0")  # Type-tree-is-atom
11002     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:1")  # Type-tree-value
11003     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:2")  # Type-tree-right
11004 $test-function-header-with-multiple-args-and-outputs:inout1:
11005     # inouts = lookup(inouts->next)
11006     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
11007     89/<- %edx 0/r32/eax
11008     # v = lookup(inouts->value)
11009     (lookup *edx *(edx+4))  # List-value List-value => eax
11010     89/<- %ebx 0/r32/eax
11011     # check v->name
11012     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
11013     (check-strings-equal %eax "b" "F - test-function-header-with-multiple-args-and-outputs/inout:1")
11014     # check v->type
11015     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
11016     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:0")  # Type-tree-is-atom
11017     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:1")  # Type-tree-value
11018     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:2")  # Type-tree-right
11019 $test-function-header-with-multiple-args-and-outputs:inout2:
11020     # inouts = lookup(inouts->next)
11021     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
11022     89/<- %edx 0/r32/eax
11023     # v = lookup(inouts->value)
11024     (lookup *edx *(edx+4))  # List-value List-value => eax
11025     89/<- %ebx 0/r32/eax
11026     # check v->name
11027     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
11028     (check-strings-equal %eax "c" "F - test-function-header-with-multiple-args-and-outputs/inout:2")
11029     # check v->type
11030     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
11031     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:0")  # Type-tree-is-atom
11032     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:1")  # Type-tree-value
11033     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:2")  # Type-tree-right
11034 $test-function-header-with-multiple-args-and-outputs:out0:
11035     # var outputs/edx: (addr list var) = lookup(result->outputs)
11036     (lookup *(ecx+0x10) *(ecx+0x14))  # Function-outputs Function-outputs => eax
11037     89/<- %edx 0/r32/eax
11038     # v = lookup(outputs->value)
11039     (lookup *edx *(edx+4))  # List-value List-value => eax
11040     89/<- %ebx 0/r32/eax
11041     # check v->name
11042     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
11043     (check-strings-equal %eax "x" "F - test-function-header-with-multiple-args-and-outputs/output:0")
11044     # check v->register
11045     (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
11046     (check-strings-equal %eax "ecx" "F - test-function-header-with-multiple-args-and-outputs/output:0/register")
11047     # check v->type
11048     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
11049     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:0")  # Type-tree-is-atom
11050     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:1")  # Type-tree-value
11051     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:2")  # Type-tree-right
11052 $test-function-header-with-multiple-args-and-outputs:out1:
11053     # outputs = lookup(outputs->next)
11054     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
11055     89/<- %edx 0/r32/eax
11056     # v = lookup(inouts->value)
11057     (lookup *edx *(edx+4))  # List-value List-value => eax
11058     89/<- %ebx 0/r32/eax
11059     # check v->name
11060     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
11061     (check-strings-equal %eax "y" "F - test-function-header-with-multiple-args-and-outputs/output:1")
11062     # check v->register
11063     (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
11064     (check-strings-equal %eax "edx" "F - test-function-header-with-multiple-args-and-outputs/output:1/register")
11065     # check v->type
11066     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
11067     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:0")  # Type-tree-is-atom
11068     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:1")  # Type-tree-value
11069     (check-ints-equal *(eax+0c) 0 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:2")  # Type-tree-right
11070     # . epilogue
11071     89/<- %esp 5/r32/ebp
11072     5d/pop-to-ebp
11073     c3/return
11074 
11075 # format for variables with types
11076 #   x: int
11077 #   x: int,
11078 #   x/eax: int
11079 #   x/eax: int,
11080 # ignores at most one trailing comma
11081 # WARNING: modifies name
11082 parse-var-with-type:  # name: (addr slice), first-line: (addr stream byte), out: (addr handle var), err: (addr buffered-file), ed: (addr exit-descriptor)
11083     # pseudocode:
11084     #   var s: slice
11085     #   if (!slice-ends-with(name, ":"))
11086     #     abort
11087     #   --name->end to skip ':'
11088     #   next-token-from-slice(name->start, name->end, '/', s)
11089     #   new-var-from-slice(s, out)
11090     #   ## register
11091     #   next-token-from-slice(s->end, name->end, '/', s)
11092     #   if (!slice-empty?(s))
11093     #     out->register = slice-to-string(s)
11094     #   ## type
11095     #   var type: (handle type-tree) = parse-type(first-line)
11096     #   out->type = type
11097     #
11098     # . prologue
11099     55/push-ebp
11100     89/<- %ebp 4/r32/esp
11101     # . save registers
11102     50/push-eax
11103     51/push-ecx
11104     52/push-edx
11105     53/push-ebx
11106     56/push-esi
11107     57/push-edi
11108     # esi = name
11109     8b/-> *(ebp+8) 6/r32/esi
11110     # if (!slice-ends-with?(name, ":")) abort
11111     8b/-> *(esi+4) 1/r32/ecx  # Slice-end
11112     49/decrement-ecx
11113     8a/copy-byte *ecx 1/r32/CL
11114     81 4/subop/and %ecx 0xff/imm32
11115     81 7/subop/compare %ecx 0x3a/imm32/colon
11116     0f 85/jump-if-!= $parse-var-with-type:abort/disp32
11117     # --name->end to skip ':'
11118     ff 1/subop/decrement *(esi+4)
11119     # var s/ecx: slice
11120     68/push 0/imm32/end
11121     68/push 0/imm32/start
11122     89/<- %ecx 4/r32/esp
11123 $parse-var-with-type:parse-name:
11124     (next-token-from-slice *esi *(esi+4) 0x2f %ecx)  # Slice-start, Slice-end, '/'
11125 $parse-var-with-type:create-var:
11126     # new-var-from-slice(s, out)
11127     (new-var-from-slice Heap %ecx *(ebp+0x10))
11128     # save out->register
11129 $parse-var-with-type:save-register:
11130     # . var out-addr/edi: (addr var) = lookup(*out)
11131     8b/-> *(ebp+0x10) 7/r32/edi
11132     (lookup *edi *(edi+4))  # => eax
11133     89/<- %edi 0/r32/eax
11134     # . s = next-token(...)
11135     (next-token-from-slice *(ecx+4) *(esi+4) 0x2f %ecx)  # s->end, name->end, '/'
11136     # . if (!slice-empty?(s)) out->register = slice-to-string(s)
11137     {
11138 $parse-var-with-type:write-register:
11139       (slice-empty? %ecx)  # => eax
11140       3d/compare-eax-and 0/imm32/false
11141       75/jump-if-!= break/disp8
11142       # out->register = slice-to-string(s)
11143       8d/copy-address *(edi+0x18) 0/r32/eax  # Var-register
11144       (slice-to-string Heap %ecx %eax)
11145     }
11146 $parse-var-with-type:save-type:
11147     8d/copy-address *(edi+8) 0/r32/eax  # Var-type
11148     (parse-type Heap *(ebp+0xc) %eax *(ebp+0x14) *(ebp+0x18))
11149 $parse-var-with-type:end:
11150     # . reclaim locals
11151     81 0/subop/add %esp 8/imm32
11152     # . restore registers
11153     5f/pop-to-edi
11154     5e/pop-to-esi
11155     5b/pop-to-ebx
11156     5a/pop-to-edx
11157     59/pop-to-ecx
11158     58/pop-to-eax
11159     # . epilogue
11160     89/<- %esp 5/r32/ebp
11161     5d/pop-to-ebp
11162     c3/return
11163 
11164 $parse-var-with-type:abort:
11165     # error("var should have form 'name: type' in '" line "'\n")
11166     (write-buffered *(ebp+0x14) "var should have form 'name: type' in '")
11167     (flush *(ebp+0x14))
11168     (rewind-stream *(ebp+0xc))
11169     (write-stream-data *(ebp+0x14) *(ebp+0xc))
11170     (write-buffered *(ebp+0x14) "'\n")
11171     (flush *(ebp+0x14))
11172     (stop *(ebp+0x18) 1)
11173     # never gets here
11174 
11175 parse-type:  # ad: (addr allocation-descriptor), in: (addr stream byte), out: (addr handle type-tree), err: (addr buffered-file), ed: (addr exit-descriptor)
11176     # pseudocode:
11177     #   var s: slice = next-mu-token(in)
11178     #   assert s != ""
11179     #   assert s != "->"
11180     #   assert s != "{"
11181     #   assert s != "}"
11182     #   if s == ")"
11183     #     return
11184     #   out = allocate(Type-tree)
11185     #   if s != "("
11186     #     HACK: if s is an int, parse and return it
11187     #     out->is-atom? = true
11188     #     if (s[0] == "_")
11189     #       out->value = type-parameter
11190     #       out->parameter-name = slice-to-string(ad, s)
11191     #     else
11192     #       out->value = pos-or-insert-slice(Type-id, s)
11193     #     return
11194     #   out->left = parse-type(ad, in)
11195     #   out->right = parse-type-tree(ad, in)
11196     #
11197     # . prologue
11198     55/push-ebp
11199     89/<- %ebp 4/r32/esp
11200     # . save registers
11201     50/push-eax
11202     51/push-ecx
11203     52/push-edx
11204     # clear out
11205     (zero-out *(ebp+0x10) *Handle-size)
11206     # var s/ecx: slice
11207     68/push 0/imm32
11208     68/push 0/imm32
11209     89/<- %ecx 4/r32/esp
11210     # s = next-mu-token(in)
11211     (next-mu-token *(ebp+0xc) %ecx)
11212 #?     (write-buffered Stderr "tok: ")
11213 #?     (write-slice-buffered Stderr %ecx)
11214 #?     (write-buffered Stderr "$\n")
11215 #?     (flush Stderr)
11216     # assert s != ""
11217     (slice-equal? %ecx "")  # => eax
11218     3d/compare-eax-and 0/imm32/false
11219     0f 85/jump-if-!= $parse-type:abort/disp32
11220     # assert s != "{"
11221     (slice-equal? %ecx "{")  # => eax
11222     3d/compare-eax-and 0/imm32/false
11223     0f 85/jump-if-!= $parse-type:abort/disp32
11224     # assert s != "}"
11225     (slice-equal? %ecx "}")  # => eax
11226     3d/compare-eax-and 0/imm32/false
11227     0f 85/jump-if-!= $parse-type:abort/disp32
11228     # assert s != "->"
11229     (slice-equal? %ecx "->")  # => eax
11230     3d/compare-eax-and 0/imm32/false
11231     0f 85/jump-if-!= $parse-type:abort/disp32
11232     # if (s == ")") return
11233     (slice-equal? %ecx ")")  # => eax
11234     3d/compare-eax-and 0/imm32/false
11235     0f 85/jump-if-!= $parse-type:end/disp32
11236     # out = new tree
11237     (allocate *(ebp+8) *Type-tree-size *(ebp+0x10))
11238     # var out-addr/edx: (addr type-tree) = lookup(*out)
11239     8b/-> *(ebp+0x10) 2/r32/edx
11240     (lookup *edx *(edx+4))  # => eax
11241     89/<- %edx 0/r32/eax
11242     {
11243       # if (s != "(") break
11244       (slice-equal? %ecx "(")  # => eax
11245       3d/compare-eax-and 0/imm32/false
11246       0f 85/jump-if-!= break/disp32
11247       # if s is a number, store it in the type's size field
11248       {
11249 $parse-type:check-for-int:
11250         # var tmp/eax: byte = *s->slice
11251         8b/-> *ecx 0/r32/eax
11252         8a/copy-byte *eax 0/r32/AL
11253         81 4/subop/and %eax 0xff/imm32
11254         # TODO: raise an error on `var x: (array int a)`
11255         (is-decimal-digit? %eax)  # => eax
11256         3d/compare-eax-and 0/imm32/false
11257         74/jump-if-= break/disp8
11258         #
11259         (is-hex-int? %ecx)  # => eax
11260         3d/compare-eax-and 0/imm32/false
11261         74/jump-if-= break/disp8
11262 $parse-type:int:
11263         (check-mu-hex-int %ecx *(ebp+0x14) *(ebp+0x18))
11264         (parse-hex-int-from-slice %ecx)  # => eax
11265         c7 0/subop/copy *(edx+4) 9/imm32/type-id-array-capacity  # Type-tree-value
11266         89/<- *(edx+8) 0/r32/eax  # Type-tree-value-size
11267         e9/jump $parse-type:end/disp32
11268       }
11269 $parse-type:atom:
11270       # out->is-atom? = true
11271       c7 0/subop/copy *edx 1/imm32/true  # Type-tree-is-atom
11272       {
11273 $parse-type:check-for-type-parameter:
11274         # var tmp/eax: byte = *s->slice
11275         8b/-> *ecx 0/r32/eax
11276         8a/copy-byte *eax 0/r32/AL
11277         81 4/subop/and %eax 0xff/imm32
11278         # if (tmp != '_') break
11279         3d/compare-eax-and 0x5f/imm32/_
11280         75/jump-if-!= break/disp8
11281 $parse-type:type-parameter:
11282         # out->value = type-parameter
11283         c7 0/subop/copy *(edx+4) 0xa/imm32/type-parameter  # Type-tree-value
11284         # out->parameter-name = slice-to-string(ad, s)
11285         8d/copy-address *(edx+8) 0/r32/eax  # Type-tree-parameter-name
11286         (slice-to-string *(ebp+8) %ecx %eax)
11287         e9/jump $parse-type:end/disp32
11288       }
11289 $parse-type:non-type-parameter:
11290       # out->value = pos-or-insert-slice(Type-id, s)
11291       (pos-or-insert-slice Type-id %ecx)  # => eax
11292       89/<- *(edx+4) 0/r32/eax  # Type-tree-value
11293       e9/jump $parse-type:end/disp32
11294     }
11295 $parse-type:non-atom:
11296     # otherwise s == "("
11297     # out->left = parse-type(ad, in)
11298     8d/copy-address *(edx+4) 0/r32/eax  # Type-tree-left
11299     (parse-type *(ebp+8) *(ebp+0xc) %eax *(ebp+0x14) *(ebp+0x18))
11300     # out->right = parse-type-tree(ad, in)
11301     8d/copy-address *(edx+0xc) 0/r32/eax  # Type-tree-right
11302     (parse-type-tree *(ebp+8) *(ebp+0xc) %eax *(ebp+0x14) *(ebp+0x18))
11303 $parse-type:end:
11304     # . reclaim locals
11305     81 0/subop/add %esp 8/imm32
11306     # . restore registers
11307     5a/pop-to-edx
11308     59/pop-to-ecx
11309     58/pop-to-eax
11310     # . epilogue
11311     89/<- %esp 5/r32/ebp
11312     5d/pop-to-ebp
11313     c3/return
11314 
11315 $parse-type:abort:
11316     # error("unexpected token when parsing type: '" s "'\n")
11317     (write-buffered *(ebp+0x14) "unexpected token when parsing type: '")
11318     (write-slice-buffered *(ebp+0x14) %ecx)
11319     (write-buffered *(ebp+0x14) "'\n")
11320     (flush *(ebp+0x14))
11321     (stop *(ebp+0x18) 1)
11322     # never gets here
11323 
11324 parse-type-tree:  # ad: (addr allocation-descriptor), in: (addr stream byte), out: (addr handle type-tree), err: (addr buffered-file), ed: (addr exit-descriptor)
11325     # pseudocode:
11326     #   var tmp: (handle type-tree) = parse-type(ad, in)
11327     #   if tmp == 0
11328     #     return 0
11329     #   out = allocate(Type-tree)
11330     #   out->left = tmp
11331     #   out->right = parse-type-tree(ad, in)
11332     #
11333     # . prologue
11334     55/push-ebp
11335     89/<- %ebp 4/r32/esp
11336     # . save registers
11337     50/push-eax
11338     51/push-ecx
11339     52/push-edx
11340     #
11341     (zero-out *(ebp+0x10) *Handle-size)
11342     # var tmp/ecx: (handle type-tree)
11343     68/push 0/imm32
11344     68/push 0/imm32
11345     89/<- %ecx 4/r32/esp
11346     # tmp = parse-type(ad, in)
11347     (parse-type *(ebp+8) *(ebp+0xc) %ecx *(ebp+0x14) *(ebp+0x18))
11348     # if (tmp == 0) return
11349     81 7/subop/compare *ecx 0/imm32
11350     74/jump-if-= $parse-type-tree:end/disp8
11351     # out = new tree
11352     (allocate *(ebp+8) *Type-tree-size *(ebp+0x10))
11353     # var out-addr/edx: (addr tree) = lookup(*out)
11354     8b/-> *(ebp+0x10) 2/r32/edx
11355     (lookup *edx *(edx+4))  # => eax
11356     89/<- %edx 0/r32/eax
11357     # out->left = tmp
11358     8b/-> *ecx 0/r32/eax
11359     89/<- *(edx+4) 0/r32/eax  # Type-tree-left
11360     8b/-> *(ecx+4) 0/r32/eax
11361     89/<- *(edx+8) 0/r32/eax  # Type-tree-left
11362     # out->right = parse-type-tree(ad, in)
11363     8d/copy-address *(edx+0xc) 0/r32/eax  # Type-tree-right
11364     (parse-type-tree *(ebp+8) *(ebp+0xc) %eax *(ebp+0x14) *(ebp+0x18))
11365 $parse-type-tree:end:
11366     # . reclaim locals
11367     81 0/subop/add %esp 8/imm32
11368     # . restore registers
11369     5a/pop-to-edx
11370     59/pop-to-ecx
11371     58/pop-to-eax
11372     # . epilogue
11373     89/<- %esp 5/r32/ebp
11374     5d/pop-to-ebp
11375     c3/return
11376 
11377 next-mu-token:  # in: (addr stream byte), out: (addr slice)
11378     # pseudocode:
11379     # start:
11380     #   skip-chars-matching-whitespace(in)
11381     #   if in->read >= in->write              # end of in
11382     #     out = {0, 0}
11383     #     return
11384     #   out->start = &in->data[in->read]
11385     #   var curr-byte/eax: byte = in->data[in->read]
11386     #   if curr->byte == ','                  # comment token
11387     #     ++in->read
11388     #     goto start
11389     #   if curr-byte == '#'                   # comment
11390     #     goto done                             # treat as eof
11391     #   if curr-byte == '"'                   # string literal
11392     #     skip-string(in)
11393     #     goto done                           # no metadata
11394     #   if curr-byte == '('
11395     #     ++in->read
11396     #     goto done
11397     #   if curr-byte == ')'
11398     #     ++in->read
11399     #     goto done
11400     #   # read a word
11401     #   while true
11402     #     if in->read >= in->write
11403     #       break
11404     #     curr-byte = in->data[in->read]
11405     #     if curr-byte == ' '
11406     #       break
11407     #     if curr-byte == '\r'
11408     #       break
11409     #     if curr-byte == '\n'
11410     #       break
11411     #     if curr-byte == '('
11412     #       break
11413     #     if curr-byte == ')'
11414     #       break
11415     #     if curr-byte == ','
11416     #       break
11417     #     ++in->read
11418     # done:
11419     #   out->end = &in->data[in->read]
11420     #
11421     # . prologue
11422     55/push-ebp
11423     89/<- %ebp 4/r32/esp
11424     # . save registers
11425     50/push-eax
11426     51/push-ecx
11427     56/push-esi
11428     57/push-edi
11429     # esi = in
11430     8b/-> *(ebp+8) 6/r32/esi
11431     # edi = out
11432     8b/-> *(ebp+0xc) 7/r32/edi
11433 $next-mu-token:start:
11434     (skip-chars-matching-whitespace %esi)
11435 $next-mu-token:check0:
11436     # if (in->read >= in->write) return out = {0, 0}
11437     # . ecx = in->read
11438     8b/-> *(esi+4) 1/r32/ecx
11439     # . if (ecx >= in->write) return out = {0, 0}
11440     3b/compare<- *esi 1/r32/ecx
11441     c7 0/subop/copy *edi 0/imm32
11442     c7 0/subop/copy *(edi+4) 0/imm32
11443     0f 8d/jump-if->= $next-mu-token:end/disp32
11444     # out->start = &in->data[in->read]
11445     8d/copy-address *(esi+ecx+0xc) 0/r32/eax
11446     89/<- *edi 0/r32/eax
11447     # var curr-byte/eax: byte = in->data[in->read]
11448     31/xor-with %eax 0/r32/eax
11449     8a/copy-byte *(esi+ecx+0xc) 0/r32/AL
11450     {
11451 $next-mu-token:check-for-comma:
11452       # if (curr-byte != ',') break
11453       3d/compare-eax-and 0x2c/imm32/comma
11454       75/jump-if-!= break/disp8
11455       # ++in->read
11456       ff 0/subop/increment *(esi+4)
11457       # restart
11458       e9/jump $next-mu-token:start/disp32
11459     }
11460     {
11461 $next-mu-token:check-for-comment:
11462       # if (curr-byte != '#') break
11463       3d/compare-eax-and 0x23/imm32/pound
11464       75/jump-if-!= break/disp8
11465       # return eof
11466       e9/jump $next-mu-token:done/disp32
11467     }
11468     {
11469 $next-mu-token:check-for-string-literal:
11470       # if (curr-byte != '"') break
11471       3d/compare-eax-and 0x22/imm32/dquote
11472       75/jump-if-!= break/disp8
11473       (skip-string %esi)
11474       # return
11475       e9/jump $next-mu-token:done/disp32
11476     }
11477     {
11478 $next-mu-token:check-for-open-paren:
11479       # if (curr-byte != '(') break
11480       3d/compare-eax-and 0x28/imm32/open-paren
11481       75/jump-if-!= break/disp8
11482       # ++in->read
11483       ff 0/subop/increment *(esi+4)
11484       # return
11485       e9/jump $next-mu-token:done/disp32
11486     }
11487     {
11488 $next-mu-token:check-for-close-paren:
11489       # if (curr-byte != ')') break
11490       3d/compare-eax-and 0x29/imm32/close-paren
11491       75/jump-if-!= break/disp8
11492       # ++in->read
11493       ff 0/subop/increment *(esi+4)
11494       # return
11495       e9/jump $next-mu-token:done/disp32
11496     }
11497     {
11498 $next-mu-token:regular-word-without-metadata:
11499       # if (in->read >= in->write) break
11500       # . ecx = in->read
11501       8b/-> *(esi+4) 1/r32/ecx
11502       # . if (ecx >= in->write) break
11503       3b/compare<- *esi 1/r32/ecx
11504       7d/jump-if->= break/disp8
11505       # var c/eax: byte = in->data[in->read]
11506       31/xor-with %eax 0/r32/eax
11507       8a/copy-byte *(esi+ecx+0xc) 0/r32/AL
11508       # if (c == ' ') break
11509       3d/compare-eax-and 0x20/imm32/space
11510       74/jump-if-= break/disp8
11511       # if (c == '\r') break
11512       3d/compare-eax-and 0xd/imm32/carriage-return
11513       74/jump-if-= break/disp8
11514       # if (c == '\n') break
11515       3d/compare-eax-and 0xa/imm32/newline
11516       74/jump-if-= break/disp8
11517       # if (c == '(') break
11518       3d/compare-eax-and 0x28/imm32/open-paren
11519       0f 84/jump-if-= break/disp32
11520       # if (c == ')') break
11521       3d/compare-eax-and 0x29/imm32/close-paren
11522       0f 84/jump-if-= break/disp32
11523       # if (c == ',') break
11524       3d/compare-eax-and 0x2c/imm32/comma
11525       0f 84/jump-if-= break/disp32
11526       # ++in->read
11527       ff 0/subop/increment *(esi+4)
11528       #
11529       e9/jump loop/disp32
11530     }
11531 $next-mu-token:done:
11532     # out->end = &in->data[in->read]
11533     8b/-> *(esi+4) 1/r32/ecx
11534     8d/copy-address *(esi+ecx+0xc) 0/r32/eax
11535     89/<- *(edi+4) 0/r32/eax
11536 $next-mu-token:end:
11537     # . restore registers
11538     5f/pop-to-edi
11539     5e/pop-to-esi
11540     59/pop-to-ecx
11541     58/pop-to-eax
11542     # . epilogue
11543     89/<- %esp 5/r32/ebp
11544     5d/pop-to-ebp
11545     c3/return
11546 
11547 pos-or-insert-slice:  # arr: (addr stream (addr array byte)), s: (addr slice) -> index/eax: int
11548     # . prologue
11549     55/push-ebp
11550     89/<- %ebp 4/r32/esp
11551     # if (pos-slice(arr, s) != -1) return it
11552     (pos-slice *(ebp+8) *(ebp+0xc))  # => eax
11553     3d/compare-eax-and -1/imm32
11554     75/jump-if-!= $pos-or-insert-slice:end/disp8
11555 $pos-or-insert-slice:insert:
11556     # var s2/eax: (handle array byte)
11557     68/push 0/imm32
11558     68/push 0/imm32
11559     89/<- %eax 4/r32/esp
11560     (slice-to-string Heap *(ebp+0xc) %eax)
11561     # throw away alloc-id
11562     (lookup *eax *(eax+4))  # => eax
11563     (write-int *(ebp+8) %eax)
11564     (pos-slice *(ebp+8) *(ebp+0xc))  # => eax
11565 $pos-or-insert-slice:end:
11566     # . reclaim locals
11567     81 0/subop/add %esp 8/imm32
11568     # . epilogue
11569     89/<- %esp 5/r32/ebp
11570     5d/pop-to-ebp
11571     c3/return
11572 
11573 # return the index in an array of strings matching 's', -1 if not found
11574 # index is denominated in elements, not bytes
11575 pos-slice:  # arr: (addr stream (addr array byte)), s: (addr slice) -> index/eax: int
11576     # . prologue
11577     55/push-ebp
11578     89/<- %ebp 4/r32/esp
11579     # . save registers
11580     51/push-ecx
11581     52/push-edx
11582     53/push-ebx
11583     56/push-esi
11584 #?     (write-buffered Stderr "pos-slice: ")
11585 #?     (write-slice-buffered Stderr *(ebp+0xc))
11586 #?     (write-buffered Stderr "\n")
11587 #?     (flush Stderr)
11588     # esi = arr
11589     8b/-> *(ebp+8) 6/r32/esi
11590     # var index/ecx: int = 0
11591     b9/copy-to-ecx 0/imm32
11592     # var curr/edx: (addr (addr array byte)) = arr->data
11593     8d/copy-address *(esi+0xc) 2/r32/edx
11594     # var max/ebx: (addr (addr array byte)) = &arr->data[arr->write]
11595     8b/-> *esi 3/r32/ebx
11596     8d/copy-address *(esi+ebx+0xc) 3/r32/ebx
11597     {
11598 #?       (write-buffered Stderr "  ")
11599 #?       (write-int32-hex-buffered Stderr %ecx)
11600 #?       (write-buffered Stderr "\n")
11601 #?       (flush Stderr)
11602       # if (curr >= max) return -1
11603       39/compare %edx 3/r32/ebx
11604       b8/copy-to-eax -1/imm32
11605       73/jump-if-addr>= $pos-slice:end/disp8
11606       # if (slice-equal?(s, *curr)) break
11607       (slice-equal? *(ebp+0xc) *edx)  # => eax
11608       3d/compare-eax-and 0/imm32/false
11609       75/jump-if-!= break/disp8
11610       # ++index
11611       41/increment-ecx
11612       # curr += 4
11613       81 0/subop/add %edx 4/imm32
11614       #
11615       eb/jump loop/disp8
11616     }
11617     # return index
11618     89/<- %eax 1/r32/ecx
11619 $pos-slice:end:
11620 #?     (write-buffered Stderr "=> ")
11621 #?     (write-int32-hex-buffered Stderr %eax)
11622 #?     (write-buffered Stderr "\n")
11623     # . restore registers
11624     5e/pop-to-esi
11625     5b/pop-to-ebx
11626     5a/pop-to-edx
11627     59/pop-to-ecx
11628     # . epilogue
11629     89/<- %esp 5/r32/ebp
11630     5d/pop-to-ebp
11631     c3/return
11632 
11633 test-parse-var-with-type:
11634     # . prologue
11635     55/push-ebp
11636     89/<- %ebp 4/r32/esp
11637     # setup
11638     8b/-> *Primitive-type-ids 0/r32/eax
11639     89/<- *Type-id 0/r32/eax  # stream-write
11640     # (eax..ecx) = "x:"
11641     b8/copy-to-eax "x:"/imm32
11642     8b/-> *eax 1/r32/ecx
11643     8d/copy-address *(eax+ecx+4) 1/r32/ecx
11644     05/add-to-eax 4/imm32
11645     # var slice/ecx: slice = {eax, ecx}
11646     51/push-ecx
11647     50/push-eax
11648     89/<- %ecx 4/r32/esp
11649     # _test-input-stream contains "int"
11650     (clear-stream _test-input-stream)
11651     (write _test-input-stream "int")
11652     # var v/edx: (handle var)
11653     68/push 0/imm32
11654     68/push 0/imm32
11655     89/<- %edx 4/r32/esp
11656     #
11657     (parse-var-with-type %ecx _test-input-stream %edx Stderr 0)
11658     # var v-addr/edx: (addr var) = lookup(v)
11659     (lookup *edx *(edx+4))  # => eax
11660     89/<- %edx 0/r32/eax
11661     # check v-addr->name
11662     (lookup *edx *(edx+4))  # Var-name Var-name => eax
11663     (check-strings-equal %eax "x" "F - test-parse-var-with-type/name")
11664     # check v-addr->type
11665     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
11666     (check-ints-equal *eax 1 "F - test-parse-var-with-type/type:0")  # Type-tree-is-atom
11667     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-type/type:1")  # Type-tree-value
11668     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-type/type:2")  # Type-tree-right
11669     # . epilogue
11670     89/<- %esp 5/r32/ebp
11671     5d/pop-to-ebp
11672     c3/return
11673 
11674 test-parse-var-with-type-and-register:
11675     # . prologue
11676     55/push-ebp
11677     89/<- %ebp 4/r32/esp
11678     # setup
11679     8b/-> *Primitive-type-ids 0/r32/eax
11680     89/<- *Type-id 0/r32/eax  # stream-write
11681     # (eax..ecx) = "x/eax:"
11682     b8/copy-to-eax "x/eax:"/imm32
11683     8b/-> *eax 1/r32/ecx
11684     8d/copy-address *(eax+ecx+4) 1/r32/ecx
11685     05/add-to-eax 4/imm32
11686     # var slice/ecx: slice = {eax, ecx}
11687     51/push-ecx
11688     50/push-eax
11689     89/<- %ecx 4/r32/esp
11690     # _test-input-stream contains "int"
11691     (clear-stream _test-input-stream)
11692     (write _test-input-stream "int")
11693     # var v/edx: (handle var)
11694     68/push 0/imm32
11695     68/push 0/imm32
11696     89/<- %edx 4/r32/esp
11697     #
11698     (parse-var-with-type %ecx _test-input-stream %edx Stderr 0)
11699     # var v-addr/edx: (addr var) = lookup(v)
11700     (lookup *edx *(edx+4))  # => eax
11701     89/<- %edx 0/r32/eax
11702     # check v-addr->name
11703     (lookup *edx *(edx+4))  # Var-name Var-name => eax
11704     (check-strings-equal %eax "x" "F - test-parse-var-with-type-and-register/name")
11705     # check v-addr->register
11706     (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
11707     (check-strings-equal %eax "eax" "F - test-parse-var-with-type-and-register/register")
11708     # check v-addr->type
11709     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
11710     (check-ints-equal *eax 1 "F - test-parse-var-with-type-and-register/type:0")  # Type-tree-is-atom
11711     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-type-and-register/type:1")  # Type-tree-left
11712     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-type-and-register/type:2")  # Type-tree-right
11713     # . epilogue
11714     89/<- %esp 5/r32/ebp
11715     5d/pop-to-ebp
11716     c3/return
11717 
11718 test-parse-var-with-trailing-characters:
11719     # . prologue
11720     55/push-ebp
11721     89/<- %ebp 4/r32/esp
11722     # setup
11723     8b/-> *Primitive-type-ids 0/r32/eax
11724     89/<- *Type-id 0/r32/eax  # stream-write
11725     # (eax..ecx) = "x:"
11726     b8/copy-to-eax "x:"/imm32
11727     8b/-> *eax 1/r32/ecx
11728     8d/copy-address *(eax+ecx+4) 1/r32/ecx
11729     05/add-to-eax 4/imm32
11730     # var slice/ecx: slice = {eax, ecx}
11731     51/push-ecx
11732     50/push-eax
11733     89/<- %ecx 4/r32/esp
11734     # _test-input-stream contains "int,"
11735     (clear-stream _test-input-stream)
11736     (write _test-input-stream "int,")
11737     # var v/edx: (handle var)
11738     68/push 0/imm32
11739     68/push 0/imm32
11740     89/<- %edx 4/r32/esp
11741     #
11742     (parse-var-with-type %ecx _test-input-stream %edx Stderr 0)
11743     # var v-addr/edx: (addr var) = lookup(v)
11744     (lookup *edx *(edx+4))  # => eax
11745     89/<- %edx 0/r32/eax
11746     # check v-addr->name
11747     (lookup *edx *(edx+4))  # Var-name Var-name => eax
11748     (check-strings-equal %eax "x" "F - test-parse-var-with-trailing-characters/name")
11749     # check v-addr->register
11750     (check-ints-equal *(edx+0x18) 0 "F - test-parse-var-with-trailing-characters/register")  # Var-register
11751     # check v-addr->type
11752     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
11753     (check-ints-equal *eax 1 "F - test-parse-var-with-trailing-characters/type:0")  # Type-tree-is-atom
11754     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-trailing-characters/type:1")  # Type-tree-left
11755     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-trailing-characters/type:1")  # Type-tree-right
11756     # . epilogue
11757     89/<- %esp 5/r32/ebp
11758     5d/pop-to-ebp
11759     c3/return
11760 
11761 test-parse-var-with-register-and-trailing-characters:
11762     # . prologue
11763     55/push-ebp
11764     89/<- %ebp 4/r32/esp
11765     # setup
11766     8b/-> *Primitive-type-ids 0/r32/eax
11767     89/<- *Type-id 0/r32/eax  # stream-write
11768     # (eax..ecx) = "x/eax:"
11769     b8/copy-to-eax "x/eax:"/imm32
11770     8b/-> *eax 1/r32/ecx
11771     8d/copy-address *(eax+ecx+4) 1/r32/ecx
11772     05/add-to-eax 4/imm32
11773     # var slice/ecx: slice = {eax, ecx}
11774     51/push-ecx
11775     50/push-eax
11776     89/<- %ecx 4/r32/esp
11777     # _test-input-stream contains "int,"
11778     (clear-stream _test-input-stream)
11779     (write _test-input-stream "int,")
11780     # var v/edx: (handle var)
11781     68/push 0/imm32
11782     68/push 0/imm32
11783     89/<- %edx 4/r32/esp
11784     #
11785     (parse-var-with-type %ecx _test-input-stream %edx Stderr 0)
11786     # var v-addr/edx: (addr var) = lookup(v)
11787     (lookup *edx *(edx+4))  # => eax
11788     89/<- %edx 0/r32/eax
11789     # check v-addr->name
11790     (lookup *edx *(edx+4))  # Var-name Var-name => eax
11791     (check-strings-equal %eax "x" "F - test-parse-var-with-register-and-trailing-characters/name")
11792     # check v-addr->register
11793     (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
11794     (check-strings-equal %eax "eax" "F - test-parse-var-with-register-and-trailing-characters/register")
11795     # check v-addr->type
11796     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
11797     (check-ints-equal *eax 1 "F - test-parse-var-with-register-and-trailing-characters/type:0")  # Type-tree-is-atom
11798     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-register-and-trailing-characters/type:1")  # Type-tree-left
11799     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-register-and-trailing-characters/type:2")  # Type-tree-right
11800     # . epilogue
11801     89/<- %esp 5/r32/ebp
11802     5d/pop-to-ebp
11803     c3/return
11804 
11805 test-parse-var-with-compound-type:
11806     # . prologue
11807     55/push-ebp
11808     89/<- %ebp 4/r32/esp
11809     # setup
11810     8b/-> *Primitive-type-ids 0/r32/eax
11811     89/<- *Type-id 0/r32/eax  # stream-write
11812     # (eax..ecx) = "x:"
11813     b8/copy-to-eax "x:"/imm32
11814     8b/-> *eax 1/r32/ecx
11815     8d/copy-address *(eax+ecx+4) 1/r32/ecx
11816     05/add-to-eax 4/imm32
11817     # var slice/ecx: slice = {eax, ecx}
11818     51/push-ecx
11819     50/push-eax
11820     89/<- %ecx 4/r32/esp
11821     # _test-input-stream contains "(addr int)"
11822     (clear-stream _test-input-stream)
11823     (write _test-input-stream "(addr int)")
11824     # var v/edx: (handle var)
11825     68/push 0/imm32
11826     68/push 0/imm32
11827     89/<- %edx 4/r32/esp
11828     #
11829     (parse-var-with-type %ecx _test-input-stream %edx Stderr 0)
11830     # var v-addr/edx: (addr var) = lookup(v)
11831     (lookup *edx *(edx+4))  # => eax
11832     89/<- %edx 0/r32/eax
11833     # check v-addr->name
11834     (lookup *edx *(edx+4))  # Var-name Var-name => eax
11835     (check-strings-equal %eax "x" "F - test-parse-var-with-compound-type/name")
11836     # check v-addr->register
11837     (check-ints-equal *(edx+0x18) 0 "F - test-parse-var-with-compound-type/register")  # Var-register
11838     # - check v-addr->type
11839     # var type/edx: (addr type-tree) = var->type
11840     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
11841     89/<- %edx 0/r32/eax
11842     # type is a non-atom
11843     (check-ints-equal *edx 0 "F - test-parse-var-with-compound-type/type:0")  # Type-tree-is-atom
11844     # type->left == atom(addr)
11845     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
11846     (check-ints-equal *eax 1 "F - test-parse-var-with-compound-type/type:1")  # Type-tree-is-atom
11847     (check-ints-equal *(eax+4) 2 "F - test-parse-var-with-compound-type/type:2")  # Type-tree-value
11848     # type->right->left == atom(int)
11849     (lookup *(edx+0xc) *(edx+0x10))  # Type-tree-right Type-tree-right => eax
11850     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
11851     (check-ints-equal *eax 1 "F - test-parse-var-with-compound-type/type:3")  # Type-tree-is-atom
11852     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-compound-type/type:4")  # Type-tree-value
11853     # type->right->right == null
11854     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-compound-type/type:5")  # Type-tree-right
11855     # . epilogue
11856     89/<- %esp 5/r32/ebp
11857     5d/pop-to-ebp
11858     c3/return
11859 
11860 # identifier starts with a letter or '$' or '_'
11861 # no constraints at the moment on later letters
11862 # all we really want to do so far is exclude '{', '}' and '->'
11863 is-identifier?:  # in: (addr slice) -> result/eax: boolean
11864     # . prologue
11865     55/push-ebp
11866     89/<- %ebp 4/r32/esp
11867     # if (slice-empty?(in)) return false
11868     (slice-empty? *(ebp+8))  # => eax
11869     3d/compare-eax-and 0/imm32/false
11870     75/jump-if-!= $is-identifier?:false/disp8
11871     # var c/eax: byte = *in->start
11872     8b/-> *(ebp+8) 0/r32/eax
11873     8b/-> *eax 0/r32/eax
11874     8a/copy-byte *eax 0/r32/AL
11875     81 4/subop/and %eax 0xff/imm32
11876     # if (c == '$') return true
11877     3d/compare-eax-and 0x24/imm32/$
11878     74/jump-if-= $is-identifier?:true/disp8
11879     # if (c == '_') return true
11880     3d/compare-eax-and 0x5f/imm32/_
11881     74/jump-if-= $is-identifier?:true/disp8
11882     # drop case
11883     25/and-eax-with 0x5f/imm32
11884     # if (c < 'A') return false
11885     3d/compare-eax-and 0x41/imm32/A
11886     7c/jump-if-< $is-identifier?:false/disp8
11887     # if (c > 'Z') return false
11888     3d/compare-eax-and 0x5a/imm32/Z
11889     7f/jump-if-> $is-identifier?:false/disp8
11890     # otherwise return true
11891 $is-identifier?:true:
11892     b8/copy-to-eax 1/imm32/true
11893     eb/jump $is-identifier?:end/disp8
11894 $is-identifier?:false:
11895     b8/copy-to-eax 0/imm32/false
11896 $is-identifier?:end:
11897     # . epilogue
11898     89/<- %esp 5/r32/ebp
11899     5d/pop-to-ebp
11900     c3/return
11901 
11902 test-is-identifier-dollar:
11903     # . prologue
11904     55/push-ebp
11905     89/<- %ebp 4/r32/esp
11906     # (eax..ecx) = "$a"
11907     b8/copy-to-eax "$a"/imm32
11908     8b/-> *eax 1/r32/ecx
11909     8d/copy-address *(eax+ecx+4) 1/r32/ecx
11910     05/add-to-eax 4/imm32
11911     # var slice/ecx: slice = {eax, ecx}
11912     51/push-ecx
11913     50/push-eax
11914     89/<- %ecx 4/r32/esp
11915     #
11916     (is-identifier? %ecx)
11917     (check-ints-equal %eax 1 "F - test-is-identifier-dollar")
11918     # . epilogue
11919     89/<- %esp 5/r32/ebp
11920     5d/pop-to-ebp
11921     c3/return
11922 
11923 test-is-identifier-underscore:
11924     # . prologue
11925     55/push-ebp
11926     89/<- %ebp 4/r32/esp
11927     # (eax..ecx) = "_a"
11928     b8/copy-to-eax "_a"/imm32
11929     8b/-> *eax 1/r32/ecx
11930     8d/copy-address *(eax+ecx+4) 1/r32/ecx
11931     05/add-to-eax 4/imm32
11932     # var slice/ecx: slice = {eax, ecx}
11933     51/push-ecx
11934     50/push-eax
11935     89/<- %ecx 4/r32/esp
11936     #
11937     (is-identifier? %ecx)
11938     (check-ints-equal %eax 1 "F - test-is-identifier-underscore")
11939     # . epilogue
11940     89/<- %esp 5/r32/ebp
11941     5d/pop-to-ebp
11942     c3/return
11943 
11944 test-is-identifier-a:
11945     # . prologue
11946     55/push-ebp
11947     89/<- %ebp 4/r32/esp
11948     # (eax..ecx) = "a$"
11949     b8/copy-to-eax "a$"/imm32
11950     8b/-> *eax 1/r32/ecx
11951     8d/copy-address *(eax+ecx+4) 1/r32/ecx
11952     05/add-to-eax 4/imm32
11953     # var slice/ecx: slice = {eax, ecx}
11954     51/push-ecx
11955     50/push-eax
11956     89/<- %ecx 4/r32/esp
11957     #
11958     (is-identifier? %ecx)
11959     (check-ints-equal %eax 1 "F - test-is-identifier-a")
11960     # . epilogue
11961     89/<- %esp 5/r32/ebp
11962     5d/pop-to-ebp
11963     c3/return
11964 
11965 test-is-identifier-z:
11966     # . prologue
11967     55/push-ebp
11968     89/<- %ebp 4/r32/esp
11969     # (eax..ecx) = "z$"
11970     b8/copy-to-eax "z$"/imm32
11971     8b/-> *eax 1/r32/ecx
11972     8d/copy-address *(eax+ecx+4) 1/r32/ecx
11973     05/add-to-eax 4/imm32
11974     # var slice/ecx: slice = {eax, ecx}
11975     51/push-ecx
11976     50/push-eax
11977     89/<- %ecx 4/r32/esp
11978     #
11979     (is-identifier? %ecx)
11980     (check-ints-equal %eax 1 "F - test-is-identifier-z")
11981     # . epilogue
11982     89/<- %esp 5/r32/ebp
11983     5d/pop-to-ebp
11984     c3/return
11985 
11986 test-is-identifier-A:
11987     # . prologue
11988     55/push-ebp
11989     89/<- %ebp 4/r32/esp
11990     # (eax..ecx) = "A$"
11991     b8/copy-to-eax "A$"/imm32
11992     8b/-> *eax 1/r32/ecx
11993     8d/copy-address *(eax+ecx+4) 1/r32/ecx
11994     05/add-to-eax 4/imm32
11995     # var slice/ecx: slice = {eax, ecx}
11996     51/push-ecx
11997     50/push-eax
11998     89/<- %ecx 4/r32/esp
11999     #
12000     (is-identifier? %ecx)
12001     (check-ints-equal %eax 1 "F - test-is-identifier-A")
12002     # . epilogue
12003     89/<- %esp 5/r32/ebp
12004     5d/pop-to-ebp
12005     c3/return
12006 
12007 test-is-identifier-Z:
12008     # . prologue
12009     55/push-ebp
12010     89/<- %ebp 4/r32/esp
12011     # (eax..ecx) = "Z$"
12012     b8/copy-to-eax "Z$"/imm32
12013     8b/-> *eax 1/r32/ecx
12014     8d/copy-address *(eax+ecx+4) 1/r32/ecx
12015     05/add-to-eax 4/imm32
12016     # var slice/ecx: slice = {eax, ecx}
12017     51/push-ecx
12018     50/push-eax
12019     89/<- %ecx 4/r32/esp
12020     #
12021     (is-identifier? %ecx)
12022     (check-ints-equal %eax 1 "F - test-is-identifier-Z")
12023     # . epilogue
12024     89/<- %esp 5/r32/ebp
12025     5d/pop-to-ebp
12026     c3/return
12027 
12028 test-is-identifier-at:
12029     # character before 'A' is invalid
12030     # . prologue
12031     55/push-ebp
12032     89/<- %ebp 4/r32/esp
12033     # (eax..ecx) = "@a"
12034     b8/copy-to-eax "@a"/imm32
12035     8b/-> *eax 1/r32/ecx
12036     8d/copy-address *(eax+ecx+4) 1/r32/ecx
12037     05/add-to-eax 4/imm32
12038     # var slice/ecx: slice = {eax, ecx}
12039     51/push-ecx
12040     50/push-eax
12041     89/<- %ecx 4/r32/esp
12042     #
12043     (is-identifier? %ecx)
12044     (check-ints-equal %eax 0 "F - test-is-identifier-@")
12045     # . epilogue
12046     89/<- %esp 5/r32/ebp
12047     5d/pop-to-ebp
12048     c3/return
12049 
12050 test-is-identifier-square-bracket:
12051     # character after 'Z' is invalid
12052     # . prologue
12053     55/push-ebp
12054     89/<- %ebp 4/r32/esp
12055     # (eax..ecx) = "[a"
12056     b8/copy-to-eax "[a"/imm32
12057     8b/-> *eax 1/r32/ecx
12058     8d/copy-address *(eax+ecx+4) 1/r32/ecx
12059     05/add-to-eax 4/imm32
12060     # var slice/ecx: slice = {eax, ecx}
12061     51/push-ecx
12062     50/push-eax
12063     89/<- %ecx 4/r32/esp
12064     #
12065     (is-identifier? %ecx)
12066     (check-ints-equal %eax 0 "F - test-is-identifier-@")
12067     # . epilogue
12068     89/<- %esp 5/r32/ebp
12069     5d/pop-to-ebp
12070     c3/return
12071 
12072 test-is-identifier-backtick:
12073     # character before 'a' is invalid
12074     # . prologue
12075     55/push-ebp
12076     89/<- %ebp 4/r32/esp
12077     # (eax..ecx) = "`a"
12078     b8/copy-to-eax "`a"/imm32
12079     8b/-> *eax 1/r32/ecx
12080     8d/copy-address *(eax+ecx+4) 1/r32/ecx
12081     05/add-to-eax 4/imm32
12082     # var slice/ecx: slice = {eax, ecx}
12083     51/push-ecx
12084     50/push-eax
12085     89/<- %ecx 4/r32/esp
12086     #
12087     (is-identifier? %ecx)
12088     (check-ints-equal %eax 0 "F - test-is-identifier-backtick")
12089     # . epilogue
12090     89/<- %esp 5/r32/ebp
12091     5d/pop-to-ebp
12092     c3/return
12093 
12094 test-is-identifier-curly-brace-open:
12095     # character after 'z' is invalid; also used for blocks
12096     # . prologue
12097     55/push-ebp
12098     89/<- %ebp 4/r32/esp
12099     # (eax..ecx) = "{a"
12100     b8/copy-to-eax "{a"/imm32
12101     8b/-> *eax 1/r32/ecx
12102     8d/copy-address *(eax+ecx+4) 1/r32/ecx
12103     05/add-to-eax 4/imm32
12104     # var slice/ecx: slice = {eax, ecx}
12105     51/push-ecx
12106     50/push-eax
12107     89/<- %ecx 4/r32/esp
12108     #
12109     (is-identifier? %ecx)
12110     (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-open")
12111     # . epilogue
12112     89/<- %esp 5/r32/ebp
12113     5d/pop-to-ebp
12114     c3/return
12115 
12116 test-is-identifier-curly-brace-close:
12117     # . prologue
12118     55/push-ebp
12119     89/<- %ebp 4/r32/esp
12120     # (eax..ecx) = "}a"
12121     b8/copy-to-eax "}a"/imm32
12122     8b/-> *eax 1/r32/ecx
12123     8d/copy-address *(eax+ecx+4) 1/r32/ecx
12124     05/add-to-eax 4/imm32
12125     # var slice/ecx: slice = {eax, ecx}
12126     51/push-ecx
12127     50/push-eax
12128     89/<- %ecx 4/r32/esp
12129     #
12130     (is-identifier? %ecx)
12131     (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-close")
12132     # . epilogue
12133     89/<- %esp 5/r32/ebp
12134     5d/pop-to-ebp
12135     c3/return
12136 
12137 test-is-identifier-hyphen:
12138     # disallow leading '-' since '->' has special meaning
12139     # . prologue
12140     55/push-ebp
12141     89/<- %ebp 4/r32/esp
12142     # (eax..ecx) = "-a"
12143     b8/copy-to-eax "-a"/imm32
12144     8b/-> *eax 1/r32/ecx
12145     8d/copy-address *(eax+ecx+4) 1/r32/ecx
12146     05/add-to-eax 4/imm32
12147     # var slice/ecx: slice = {eax, ecx}
12148     51/push-ecx
12149     50/push-eax
12150     89/<- %ecx 4/r32/esp
12151     #
12152     (is-identifier? %ecx)
12153     (check-ints-equal %eax 0 "F - test-is-identifier-hyphen")
12154     # . epilogue
12155     89/<- %esp 5/r32/ebp
12156     5d/pop-to-ebp
12157     c3/return
12158 
12159 populate-mu-function-body:  # in: (addr buffered-file), out: (addr function), vars: (addr stack live-var), err: (addr buffered-file), ed: (addr exit-descriptor)
12160     # . prologue
12161     55/push-ebp
12162     89/<- %ebp 4/r32/esp
12163     # . save registers
12164     50/push-eax
12165     56/push-esi
12166     57/push-edi
12167     # esi = in
12168     8b/-> *(ebp+8) 6/r32/esi
12169     # edi = out
12170     8b/-> *(ebp+0xc) 7/r32/edi
12171     # initialize some global state
12172     c7 0/subop/copy *Curr-block-depth 1/imm32
12173     # parse-mu-block(in, vars, out, out->body)
12174     8d/copy-address *(edi+0x18) 0/r32/eax  # Function-body
12175     (parse-mu-block %esi *(ebp+0x10) %edi %eax *(ebp+0x14) *(ebp+0x18))
12176 $populate-mu-function-body:end:
12177     # . restore registers
12178     5f/pop-to-edi
12179     5e/pop-to-esi
12180     58/pop-to-eax
12181     # . epilogue
12182     89/<- %esp 5/r32/ebp
12183     5d/pop-to-ebp
12184     c3/return
12185 
12186 # parses a block, assuming that the leading '{' has already been read by the caller
12187 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)
12188     # pseudocode:
12189     #   var line: (stream byte 512)
12190     #   var word-slice: slice
12191     #   allocate(Heap, Stmt-size, out)
12192     #   var out-addr: (addr block) = lookup(*out)
12193     #   out-addr->tag = 0/block
12194     #   out-addr->var = some unique name
12195     #   push(vars, {out-addr->var, false})
12196     #   while true                                  # line loop
12197     #     clear-stream(line)
12198     #     read-line-buffered(in, line)
12199     #     if (line->write == 0) break               # end of file
12200     #     word-slice = next-mu-token(line)
12201     #     if slice-empty?(word-slice)               # end of line
12202     #       continue
12203     #     else if slice-starts-with?(word-slice, "#")
12204     #       continue
12205     #     else if slice-equal?(word-slice, "{")
12206     #       assert(no-tokens-in(line))
12207     #       block = parse-mu-block(in, vars, fn)
12208     #       append-to-block(out-addr, block)
12209     #     else if slice-equal?(word-slice, "}")
12210     #       break
12211     #     else if slice-ends-with?(word-slice, ":")
12212     #       # TODO: error-check the rest of 'line'
12213     #       --word-slice->end to skip ':'
12214     #       named-block = parse-mu-named-block(word-slice, in, vars, fn)
12215     #       append-to-block(out-addr, named-block)
12216     #     else if slice-equal?(word-slice, "var")
12217     #       var-def = parse-mu-var-def(line, vars, fn)
12218     #       append-to-block(out-addr, var-def)
12219     #     else
12220     #       stmt = parse-mu-stmt(line, vars, fn)
12221     #       append-to-block(out-addr, stmt)
12222     #   pop(vars)
12223     #
12224     # . prologue
12225     55/push-ebp
12226     89/<- %ebp 4/r32/esp
12227     # . save registers
12228     50/push-eax
12229     51/push-ecx
12230     52/push-edx
12231     53/push-ebx
12232     57/push-edi
12233     # var line/ecx: (stream byte 512)
12234     81 5/subop/subtract %esp 0x200/imm32
12235     68/push 0x200/imm32/size
12236     68/push 0/imm32/read
12237     68/push 0/imm32/write
12238     89/<- %ecx 4/r32/esp
12239     # var word-slice/edx: slice
12240     68/push 0/imm32/end
12241     68/push 0/imm32/start
12242     89/<- %edx 4/r32/esp
12243     # allocate into out
12244     (allocate Heap *Stmt-size *(ebp+0x14))
12245     # var out-addr/edi: (addr block) = lookup(*out)
12246     8b/-> *(ebp+0x14) 7/r32/edi
12247     (lookup *edi *(edi+4))  # => eax
12248     89/<- %edi 0/r32/eax
12249     # out-addr->tag is 0 (block) by default
12250     # set out-addr->var
12251     8d/copy-address *(edi+0xc) 0/r32/eax  # Block-var
12252     (new-block-name *(ebp+0x10) %eax)
12253     # push(vars, out-addr->var)
12254     (push *(ebp+0xc) *(edi+0xc))  # Block-var
12255     (push *(ebp+0xc) *(edi+0x10))  # Block-var
12256     (push *(ebp+0xc) 0)  # false
12257     # increment *Curr-block-depth
12258     ff 0/subop/increment *Curr-block-depth
12259     {
12260 $parse-mu-block:line-loop:
12261       # line = read-line-buffered(in)
12262       (clear-stream %ecx)
12263       (read-line-buffered *(ebp+8) %ecx)
12264 #?       (write-buffered Stderr "line: ")
12265 #?       (write-stream-data Stderr %ecx)
12266 #? #?       (write-buffered Stderr Newline)  # line has its own newline
12267 #?       (flush Stderr)
12268 #?       (rewind-stream %ecx)
12269       # if (line->write == 0) break
12270       81 7/subop/compare *ecx 0/imm32
12271       0f 84/jump-if-= break/disp32
12272 #?       (write-buffered Stderr "vars:\n")
12273 #?       (dump-vars *(ebp+0xc))
12274       # word-slice = next-mu-token(line)
12275       (next-mu-token %ecx %edx)
12276 #?       (write-buffered Stderr "word: ")
12277 #?       (write-slice-buffered Stderr %edx)
12278 #?       (write-buffered Stderr Newline)
12279 #?       (flush Stderr)
12280       # if slice-empty?(word-slice) continue
12281       (slice-empty? %edx)
12282       3d/compare-eax-and 0/imm32/false
12283       0f 85/jump-if-!= loop/disp32
12284       # if (slice-starts-with?(word-slice, '#') continue
12285       # . eax = *word-slice->start
12286       8b/-> *edx 0/r32/eax
12287       8a/copy-byte *eax 0/r32/AL
12288       81 4/subop/and %eax 0xff/imm32
12289       # . if (eax == '#') continue
12290       3d/compare-eax-and 0x23/imm32/hash
12291       0f 84/jump-if-= loop/disp32
12292       # if slice-equal?(word-slice, "{")
12293       {
12294 $parse-mu-block:check-for-block:
12295         (slice-equal? %edx "{")
12296         3d/compare-eax-and 0/imm32/false
12297         74/jump-if-= break/disp8
12298         (check-no-tokens-left %ecx)
12299         # parse new block and append
12300         # . var tmp/eax: (handle block)
12301         68/push 0/imm32
12302         68/push 0/imm32
12303         89/<- %eax 4/r32/esp
12304         # .
12305         (parse-mu-block *(ebp+8) *(ebp+0xc) *(ebp+0x10) %eax *(ebp+0x18) *(ebp+0x1c))
12306         (append-to-block Heap %edi  *eax *(eax+4))
12307         # . reclaim tmp
12308         81 0/subop/add %esp 8/imm32
12309         # .
12310         e9/jump $parse-mu-block:line-loop/disp32
12311       }
12312       # if slice-equal?(word-slice, "}") break
12313 $parse-mu-block:check-for-end:
12314       (slice-equal? %edx "}")
12315       3d/compare-eax-and 0/imm32/false
12316       0f 85/jump-if-!= break/disp32
12317       # if slice-ends-with?(word-slice, ":") parse named block and append
12318       {
12319 $parse-mu-block:check-for-named-block:
12320         # . eax = *(word-slice->end-1)
12321         8b/-> *(edx+4) 0/r32/eax
12322         48/decrement-eax
12323         8a/copy-byte *eax 0/r32/AL
12324         81 4/subop/and %eax 0xff/imm32
12325         # . if (eax != ':') break
12326         3d/compare-eax-and 0x3a/imm32/colon
12327         0f 85/jump-if-!= break/disp32
12328         # TODO: error-check the rest of 'line'
12329         #
12330         # skip ':'
12331         ff 1/subop/decrement *(edx+4)  # Slice-end
12332         # var tmp/eax: (handle block)
12333         68/push 0/imm32
12334         68/push 0/imm32
12335         89/<- %eax 4/r32/esp
12336         #
12337         (parse-mu-named-block %edx *(ebp+8) *(ebp+0xc) *(ebp+0x10) %eax *(ebp+0x18) *(ebp+0x1c))
12338         (append-to-block Heap %edi  *eax *(eax+4))
12339         # reclaim tmp
12340         81 0/subop/add %esp 8/imm32
12341         #
12342         e9/jump $parse-mu-block:line-loop/disp32
12343       }
12344       # if slice-equal?(word-slice, "var")
12345       {
12346 $parse-mu-block:check-for-var:
12347         (slice-equal? %edx "var")
12348         3d/compare-eax-and 0/imm32/false
12349         74/jump-if-= break/disp8
12350         # var tmp/eax: (handle block)
12351         68/push 0/imm32
12352         68/push 0/imm32
12353         89/<- %eax 4/r32/esp
12354         #
12355         (parse-mu-var-def %ecx *(ebp+0xc) %eax *(ebp+0x10) *(ebp+0x18) *(ebp+0x1c))
12356         (append-to-block Heap %edi  *eax *(eax+4))
12357         # reclaim tmp
12358         81 0/subop/add %esp 8/imm32
12359         #
12360         e9/jump $parse-mu-block:line-loop/disp32
12361       }
12362 $parse-mu-block:regular-stmt:
12363       # otherwise
12364       # var tmp/eax: (handle block)
12365       68/push 0/imm32
12366       68/push 0/imm32
12367       89/<- %eax 4/r32/esp
12368       #
12369       (parse-mu-stmt %ecx *(ebp+0xc) *(ebp+0x10) %eax *(ebp+0x18) *(ebp+0x1c))
12370       (append-to-block Heap %edi  *eax *(eax+4))
12371       # reclaim tmp
12372       81 0/subop/add %esp 8/imm32
12373       #
12374       e9/jump loop/disp32
12375     } # end line loop
12376     (clean-up-blocks *(ebp+0xc) *Curr-block-depth *(ebp+0x10))
12377     # decrement *Curr-block-depth
12378     ff 1/subop/decrement *Curr-block-depth
12379     # pop(vars)
12380     (pop *(ebp+0xc))  # => eax
12381     (pop *(ebp+0xc))  # => eax
12382     (pop *(ebp+0xc))  # => eax
12383 $parse-mu-block:end:
12384     # . reclaim locals
12385     81 0/subop/add %esp 0x214/imm32
12386     # . restore registers
12387     5f/pop-to-edi
12388     5b/pop-to-ebx
12389     5a/pop-to-edx
12390     59/pop-to-ecx
12391     58/pop-to-eax
12392     # . epilogue
12393     89/<- %esp 5/r32/ebp
12394     5d/pop-to-ebp
12395     c3/return
12396 
12397 $parse-mu-block:abort:
12398     # error("'{' or '}' should be on its own line, but got '")
12399     (write-buffered *(ebp+0x18) "'{' or '}' should be on its own line, but got '")
12400     (rewind-stream %ecx)
12401     (write-stream-data *(ebp+0x18) %ecx)
12402     (write-buffered *(ebp+0x18) "'\n")
12403     (flush *(ebp+0x18))
12404     (stop *(ebp+0x1c) 1)
12405     # never gets here
12406 
12407 new-block-name:  # fn: (addr function), out: (addr handle var)
12408     # . prologue
12409     55/push-ebp
12410     89/<- %ebp 4/r32/esp
12411     # . save registers
12412     50/push-eax
12413     51/push-ecx
12414     52/push-edx
12415     # var n/ecx: int = len(fn->name) + 10 for an int + 2 for '$:'
12416     8b/-> *(ebp+8) 0/r32/eax
12417     (lookup *eax *(eax+4))  # Function-name Function-name => eax
12418     8b/-> *eax 0/r32/eax  # String-size
12419     05/add-to-eax 0xd/imm32  # 10 + 2 for '$:'
12420     89/<- %ecx 0/r32/eax
12421     # var name/edx: (stream byte n)
12422     29/subtract-from %esp 1/r32/ecx
12423     ff 6/subop/push %ecx
12424     68/push 0/imm32/read
12425     68/push 0/imm32/write
12426     89/<- %edx 4/r32/esp
12427     (clear-stream %edx)
12428     # eax = fn->name
12429     8b/-> *(ebp+8) 0/r32/eax
12430     (lookup *eax *(eax+4))  # Function-name Function-name => eax
12431     # construct result using Next-block-index (and increment it)
12432     (write %edx "$")
12433     (write %edx %eax)
12434     (write %edx ":")
12435     (write-int32-hex %edx *Next-block-index)
12436     ff 0/subop/increment *Next-block-index
12437     # var s/eax: slice = {name->data, name->data + name->write}  (clobbering edx)
12438     # . eax = name->write
12439     8b/-> *edx 0/r32/eax
12440     # . edx = name->data
12441     8d/copy-address *(edx+0xc) 2/r32/edx
12442     # . eax = name->write + name->data
12443     01/add-to %eax 2/r32/edx
12444     # . push {edx, eax}
12445     ff 6/subop/push %eax
12446     ff 6/subop/push %edx
12447     89/<- %eax 4/r32/esp
12448     # out = new literal(s)
12449     (new-literal Heap %eax *(ebp+0xc))
12450 #?     8b/-> *(ebp+0xc) 0/r32/eax
12451 #?     (write-buffered Stderr "type allocid in caller after new-literal: ")
12452 #?     (write-int32-hex-buffered Stderr *(eax+8))
12453 #?     (write-buffered Stderr " for var ")
12454 #?     (write-int32-hex-buffered Stderr %eax)
12455 #?     (write-buffered Stderr Newline)
12456 #?     (flush Stderr)
12457 $new-block-name:end:
12458     # . reclaim locals
12459     81 0/subop/add %ecx 0xc/imm32  # name.{read/write/len}
12460     81 0/subop/add %ecx 8/imm32  # slice
12461     01/add-to %esp 1/r32/ecx
12462     # . restore registers
12463     5a/pop-to-edx
12464     59/pop-to-ecx
12465     58/pop-to-eax
12466     # . epilogue
12467     89/<- %esp 5/r32/ebp
12468     5d/pop-to-ebp
12469     c3/return
12470 
12471 check-no-tokens-left:  # line: (addr stream byte)
12472     # . prologue
12473     55/push-ebp
12474     89/<- %ebp 4/r32/esp
12475     # . save registers
12476     50/push-eax
12477     51/push-ecx
12478     # var s/ecx: slice
12479     68/push 0/imm32/end
12480     68/push 0/imm32/start
12481     89/<- %ecx 4/r32/esp
12482     #
12483     (next-mu-token *(ebp+8) %ecx)
12484     # if slice-empty?(s) return
12485     (slice-empty? %ecx)
12486     3d/compare-eax-and 0/imm32/false
12487     75/jump-if-!= $check-no-tokens-left:end/disp8
12488     # if (slice-starts-with?(s, '#') return
12489     # . eax = *s->start
12490     8b/-> *edx 0/r32/eax
12491     8a/copy-byte *eax 0/r32/AL
12492     81 4/subop/and %eax 0xff/imm32
12493     # . if (eax == '#') continue
12494     3d/compare-eax-and 0x23/imm32/hash
12495     74/jump-if-= $check-no-tokens-left:end/disp8
12496     # abort
12497     (write-buffered Stderr "'{' or '}' should be on its own line, but got '")
12498     (rewind-stream %ecx)
12499     (write-stream 2 %ecx)
12500     (write-buffered Stderr "'\n")
12501     (flush Stderr)
12502     # . syscall(exit, 1)
12503     bb/copy-to-ebx  1/imm32
12504     e8/call syscall_exit/disp32
12505     # never gets here
12506 $check-no-tokens-left:end:
12507     # . reclaim locals
12508     81 0/subop/add %esp 8/imm32
12509     # . restore registers
12510     59/pop-to-ecx
12511     58/pop-to-eax
12512     # . epilogue
12513     89/<- %esp 5/r32/ebp
12514     5d/pop-to-ebp
12515     c3/return
12516 
12517 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)
12518     # pseudocode:
12519     #   var v: (handle var)
12520     #   new-literal(name, v)
12521     #   push(vars, {v, false})
12522     #   parse-mu-block(in, vars, fn, out)
12523     #   pop(vars)
12524     #   out->tag = block
12525     #   out->var = v
12526     #
12527     # . prologue
12528     55/push-ebp
12529     89/<- %ebp 4/r32/esp
12530     # . save registers
12531     50/push-eax
12532     51/push-ecx
12533     57/push-edi
12534     # var v/ecx: (handle var)
12535     68/push 0/imm32
12536     68/push 0/imm32
12537     89/<- %ecx 4/r32/esp
12538     #
12539     (new-literal Heap *(ebp+8) %ecx)
12540     # push(vars, v)
12541     (push *(ebp+0x10) *ecx)
12542     (push *(ebp+0x10) *(ecx+4))
12543     (push *(ebp+0x10) 0)  # false
12544     #
12545     (parse-mu-block *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c) *(ebp+0x20))
12546     # pop v off vars
12547     (pop *(ebp+0x10))  # => eax
12548     (pop *(ebp+0x10))  # => eax
12549     (pop *(ebp+0x10))  # => eax
12550     # var out-addr/edi: (addr stmt) = lookup(*out)
12551     8b/-> *(ebp+0x18) 7/r32/edi
12552     (lookup *edi *(edi+4))  # => eax
12553     89/<- %edi 0/r32/eax
12554     # out-addr->tag = named-block
12555     c7 0/subop/copy *edi 0/imm32/block  # Stmt-tag
12556     # out-addr->var = v
12557     8b/-> *ecx 0/r32/eax
12558     89/<- *(edi+0xc) 0/r32/eax  # Block-var
12559     8b/-> *(ecx+4) 0/r32/eax
12560     89/<- *(edi+0x10) 0/r32/eax  # Block-var
12561 $parse-mu-named-block:end:
12562     # . reclaim locals
12563     81 0/subop/add %esp 8/imm32
12564     # . restore registers
12565     5f/pop-to-edi
12566     59/pop-to-ecx
12567     58/pop-to-eax
12568     # . epilogue
12569     89/<- %esp 5/r32/ebp
12570     5d/pop-to-ebp
12571     c3/return
12572 
12573 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)
12574     # . prologue
12575     55/push-ebp
12576     89/<- %ebp 4/r32/esp
12577     # . save registers
12578     50/push-eax
12579     51/push-ecx
12580     52/push-edx
12581     53/push-ebx
12582     57/push-edi
12583     # edi = out
12584     8b/-> *(ebp+0x10) 7/r32/edi
12585     # var word-slice/ecx: slice
12586     68/push 0/imm32/end
12587     68/push 0/imm32/start
12588     89/<- %ecx 4/r32/esp
12589     # var v/edx: (handle var)
12590     68/push 0/imm32
12591     68/push 0/imm32
12592     89/<- %edx 4/r32/esp
12593     # v = parse-var-with-type(next-mu-token(line))
12594     (next-mu-token *(ebp+8) %ecx)
12595     (parse-var-with-type %ecx *(ebp+8) %edx *(ebp+0x18) *(ebp+0x1c))
12596     # var v-addr/eax: (addr var)
12597     (lookup *edx *(edx+4))  # => eax
12598     # v->block-depth = *Curr-block-depth
12599     8b/-> *Curr-block-depth 3/r32/ebx
12600     89/<- *(eax+0x10) 3/r32/ebx  # Var-block-depth
12601     # either v has no register and there's no more to this line
12602     8b/-> *(eax+0x18) 0/r32/eax  # Var-register
12603     3d/compare-eax-and 0/imm32
12604     {
12605       75/jump-if-!= break/disp8
12606       # TODO: disallow vars of type 'byte' on the stack
12607       # ensure that there's nothing else on this line
12608       (next-mu-token *(ebp+8) %ecx)
12609       (slice-empty? %ecx)  # => eax
12610       3d/compare-eax-and 0/imm32/false
12611       0f 84/jump-if-= $parse-mu-var-def:error2/disp32
12612       #
12613       (new-var-def Heap  *edx *(edx+4)  %edi)
12614       e9/jump $parse-mu-var-def:update-vars/disp32
12615     }
12616     # or v has a register and there's more to this line
12617     {
12618       0f 84/jump-if-= break/disp32
12619       # TODO: disallow vars of type 'byte' in registers 'esi' or 'edi'
12620       # TODO: vars of type 'byte' should only be initialized by clearing to 0
12621       # ensure that the next word is '<-'
12622       (next-mu-token *(ebp+8) %ecx)
12623       (slice-equal? %ecx "<-")  # => eax
12624       3d/compare-eax-and 0/imm32/false
12625       0f 84/jump-if-= $parse-mu-var-def:error1/disp32
12626       #
12627       (new-reg-var-def Heap  *edx *(edx+4)  %edi)
12628       (lookup *edi *(edi+4))  # => eax
12629       (add-operation-and-inputs-to-stmt %eax *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
12630     }
12631 $parse-mu-var-def:update-vars:
12632     # push 'v' at end of function
12633     (push *(ebp+0xc) *edx)
12634     (push *(ebp+0xc) *(edx+4))
12635     (push *(ebp+0xc) 0)  # Live-var-register-spilled is unused during parsing
12636 $parse-mu-var-def:end:
12637     # . reclaim locals
12638     81 0/subop/add %esp 0x10/imm32
12639     # . restore registers
12640     5f/pop-to-edi
12641     5b/pop-to-ebx
12642     5a/pop-to-edx
12643     59/pop-to-ecx
12644     58/pop-to-eax
12645     # . epilogue
12646     89/<- %esp 5/r32/ebp
12647     5d/pop-to-ebp
12648     c3/return
12649 
12650 $parse-mu-var-def:error1:
12651     (rewind-stream *(ebp+8))
12652     # error("register variable requires a valid instruction to initialize but got '" line "'\n")
12653     (write-buffered *(ebp+0x18) "register variable requires a valid instruction to initialize but got '")
12654     (flush *(ebp+0x18))
12655     (write-stream-data *(ebp+0x18) *(ebp+8))
12656     (write-buffered *(ebp+0x18) "'\n")
12657     (flush *(ebp+0x18))
12658     (stop *(ebp+0x1c) 1)
12659     # never gets here
12660 
12661 $parse-mu-var-def:error2:
12662     (rewind-stream *(ebp+8))
12663     # error("fn " fn ": var " var ": variables on the stack can't take an initializer\n")
12664     (write-buffered *(ebp+0x18) "fn ")
12665     8b/-> *(ebp+0x14) 0/r32/eax
12666     (lookup *eax *(eax+4))  # Function-name Function-name => eax
12667     (write-buffered *(ebp+0x18) %eax)
12668     (write-buffered *(ebp+0x18) ": var ")
12669     # var v-addr/eax: (addr var) = lookup(v)
12670     (lookup *edx *(edx+4))  # => eax
12671     (lookup *eax *(eax+4))  # Var-name Var-name => eax
12672     (write-buffered *(ebp+0x18) %eax)
12673     (write-buffered *(ebp+0x18) ": variables on the stack can't take an initializer\n")
12674     (flush *(ebp+0x18))
12675     (stop *(ebp+0x1c) 1)
12676     # never gets here
12677 
12678 test-parse-mu-var-def:
12679     # 'var n: int'
12680     # . prologue
12681     55/push-ebp
12682     89/<- %ebp 4/r32/esp
12683     # setup
12684     8b/-> *Primitive-type-ids 0/r32/eax
12685     89/<- *Type-id 0/r32/eax  # stream-write
12686     (clear-stream _test-input-stream)
12687     (write _test-input-stream "n: int\n")  # caller has consumed the 'var'
12688     c7 0/subop/copy *Curr-block-depth 1/imm32
12689     # var out/esi: (handle stmt)
12690     68/push 0/imm32
12691     68/push 0/imm32
12692     89/<- %esi 4/r32/esp
12693     # var vars/ecx: (stack (addr var) 16)
12694     81 5/subop/subtract %esp 0xc0/imm32
12695     68/push 0xc0/imm32/size
12696     68/push 0/imm32/top
12697     89/<- %ecx 4/r32/esp
12698     (clear-stack %ecx)
12699     # convert
12700     (parse-mu-var-def _test-input-stream %ecx %esi 0 Stderr 0)
12701     # var out-addr/esi: (addr stmt)
12702     (lookup *esi *(esi+4))  # => eax
12703     89/<- %esi 0/r32/eax
12704     #
12705     (check-ints-equal *esi 2 "F - test-parse-mu-var-def/tag")  # Stmt-tag is var-def
12706     # var v/ecx: (addr var) = lookup(out->var)
12707     (lookup *(esi+4) *(esi+8))  # Vardef-var Vardef-var => eax
12708     89/<- %ecx 0/r32/eax
12709     # v->name
12710     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
12711     (check-strings-equal %eax "n" "F - test-parse-mu-var-def/var-name")
12712     # v->register
12713     (check-ints-equal *(ecx+0x18) 0 "F - test-parse-mu-var-def/var-register")  # Var-register
12714     # v->block-depth
12715     (check-ints-equal *(ecx+0x10) 1 "F - test-parse-mu-var-def/output-block-depth")  # Var-block-depth
12716     # v->type == int
12717     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
12718     (check-ints-equal *eax 1 "F - test-parse-mu-var-def/var-type:0")  # Type-tree-is-atom
12719     (check-ints-equal *(eax+4) 1 "F - test-parse-mu-var-def/var-type:1")  # Type-tree-value
12720     (check-ints-equal *(eax+0xc) 0 "F - test-parse-mu-var-def/var-type:2")  # Type-tree-right
12721     # . epilogue
12722     89/<- %esp 5/r32/ebp
12723     5d/pop-to-ebp
12724     c3/return
12725 
12726 test-parse-mu-reg-var-def:
12727     # 'var n/eax: int <- copy 0'
12728     # . prologue
12729     55/push-ebp
12730     89/<- %ebp 4/r32/esp
12731     # setup
12732     8b/-> *Primitive-type-ids 0/r32/eax
12733     89/<- *Type-id 0/r32/eax  # stream-write
12734     (clear-stream _test-input-stream)
12735     (write _test-input-stream "n/eax: int <- copy 0\n")  # caller has consumed the 'var'
12736     c7 0/subop/copy *Curr-block-depth 1/imm32
12737     # var out/esi: (handle stmt)
12738     68/push 0/imm32
12739     68/push 0/imm32
12740     89/<- %esi 4/r32/esp
12741     # var vars/ecx: (stack (addr var) 16)
12742     81 5/subop/subtract %esp 0xc0/imm32
12743     68/push 0xc0/imm32/size
12744     68/push 0/imm32/top
12745     89/<- %ecx 4/r32/esp
12746     (clear-stack %ecx)
12747     # convert
12748     (parse-mu-var-def _test-input-stream %ecx %esi 0 Stderr 0)
12749     # var out-addr/esi: (addr stmt)
12750     (lookup *esi *(esi+4))  # => eax
12751     89/<- %esi 0/r32/eax
12752     #
12753     (check-ints-equal *esi 3 "F - test-parse-mu-reg-var-def/tag")  # Stmt-tag is reg-var-def
12754     # var v/ecx: (addr var) = lookup(out->outputs->value)
12755     # . eax: (addr stmt-var) = lookup(out->outputs)
12756     (lookup *(esi+0x14) *(esi+0x18))  # Regvardef-outputs Regvardef-outputs => eax
12757     # .
12758     (check-ints-equal *(eax+8) 0 "F - test-parse-mu-reg-var-def/single-output")  # Stmt-var-next
12759     # . eax: (addr var) = lookup(eax->value)
12760     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
12761     # . ecx = eax
12762     89/<- %ecx 0/r32/eax
12763     # v->name
12764     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
12765     (check-strings-equal %eax "n" "F - test-parse-mu-reg-var-def/output-name")  # Var-name
12766     # v->register
12767     (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
12768     (check-strings-equal %eax "eax" "F - test-parse-mu-reg-var-def/output-register")
12769     # v->block-depth
12770     (check-ints-equal *(ecx+0x10) 1 "F - test-parse-mu-reg-var-def/output-block-depth")  # Var-block-depth
12771     # v->type == int
12772     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
12773     (check-ints-equal *eax 1 "F - test-parse-mu-reg-var-def/output-type:0")  # Type-tree-is-atom
12774     (check-ints-equal *(eax+4) 1 "F - test-parse-mu-reg-var-def/output-type:1")  # Type-tree-value
12775     (check-ints-equal *(eax+0xc) 0 "F - test-parse-mu-reg-var-def/output-type:2")  # Type-tree-right
12776     # . epilogue
12777     89/<- %esp 5/r32/ebp
12778     5d/pop-to-ebp
12779     c3/return
12780 
12781 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)
12782     # pseudocode:
12783     #   var name: slice
12784     #   allocate(Heap, Stmt-size, out)
12785     #   var out-addr: (addr stmt) = lookup(*out)
12786     #   out-addr->tag = stmt
12787     #   if stmt-has-outputs?(line)
12788     #     while true
12789     #       name = next-mu-token(line)
12790     #       if (name == '<-') break
12791     #       assert(is-identifier?(name))
12792     #       var v: (handle var) = lookup-var(name, vars)
12793     #       out-addr->outputs = append(v, out-addr->outputs)
12794     #   add-operation-and-inputs-to-stmt(out-addr, line, vars)
12795     #
12796     # . prologue
12797     55/push-ebp
12798     89/<- %ebp 4/r32/esp
12799     # . save registers
12800     50/push-eax
12801     51/push-ecx
12802     52/push-edx
12803     53/push-ebx
12804     57/push-edi
12805     # var name/ecx: slice
12806     68/push 0/imm32/end
12807     68/push 0/imm32/start
12808     89/<- %ecx 4/r32/esp
12809     # var is-deref?/edx: boolean = false
12810     ba/copy-to-edx 0/imm32/false
12811     # var v: (handle var)
12812     68/push 0/imm32
12813     68/push 0/imm32
12814     89/<- %ebx 4/r32/esp
12815     #
12816     (allocate Heap *Stmt-size *(ebp+0x14))
12817     # var out-addr/edi: (addr stmt) = lookup(*out)
12818     8b/-> *(ebp+0x14) 7/r32/edi
12819     (lookup *edi *(edi+4))  # => eax
12820     89/<- %edi 0/r32/eax
12821     # out-addr->tag = 1/stmt
12822     c7 0/subop/copy *edi 1/imm32/stmt1  # Stmt-tag
12823     {
12824       (stmt-has-outputs? *(ebp+8))
12825       3d/compare-eax-and 0/imm32/false
12826       0f 84/jump-if-= break/disp32
12827       {
12828 $parse-mu-stmt:read-outputs:
12829         # name = next-mu-token(line)
12830         (next-mu-token *(ebp+8) %ecx)
12831         # if slice-empty?(word-slice) break
12832         (slice-empty? %ecx)  # => eax
12833         3d/compare-eax-and 0/imm32/false
12834         0f 85/jump-if-!= break/disp32
12835         # if (name == "<-") break
12836         (slice-equal? %ecx "<-")  # => eax
12837         3d/compare-eax-and 0/imm32/false
12838         0f 85/jump-if-!= break/disp32
12839         # is-deref? = false
12840         ba/copy-to-edx 0/imm32/false
12841         # if (slice-starts-with?(name, '*')) ++name->start and set is-deref?
12842         8b/-> *ecx 0/r32/eax  # Slice-start
12843         8a/copy-byte *eax 0/r32/AL
12844         81 4/subop/and %eax 0xff/imm32
12845         3d/compare-eax-and 0x2a/imm32/asterisk
12846         {
12847           75/jump-if-!= break/disp8
12848           ff 0/subop/increment *ecx
12849           ba/copy-to-edx 1/imm32/true
12850         }
12851         # assert(is-identifier?(name))
12852         (is-identifier? %ecx)  # => eax
12853         3d/compare-eax-and 0/imm32/false
12854         0f 84/jump-if-= $parse-mu-stmt:abort/disp32
12855         #
12856         (lookup-var %ecx *(ebp+0xc) %ebx *(ebp+0x10) *(ebp+0x18) *(ebp+0x1c))
12857         8d/copy-address *(edi+0x14) 0/r32/eax  # Stmt1-outputs
12858         (append-stmt-var Heap  *ebx *(ebx+4)  *(edi+0x14) *(edi+0x18)  %edx  %eax)  # Stmt1-outputs
12859         #
12860         e9/jump loop/disp32
12861       }
12862     }
12863     (add-operation-and-inputs-to-stmt %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x18) *(ebp+0x1c))
12864 $parse-mu-stmt:end:
12865     # . reclaim locals
12866     81 0/subop/add %esp 0x10/imm32
12867     # . restore registers
12868     5f/pop-to-edi
12869     5b/pop-to-ebx
12870     5a/pop-to-edx
12871     59/pop-to-ecx
12872     58/pop-to-eax
12873     # . epilogue
12874     89/<- %esp 5/r32/ebp
12875     5d/pop-to-ebp
12876     c3/return
12877 
12878 $parse-mu-stmt:abort:
12879     # error("invalid identifier '" name "'\n")
12880     (write-buffered *(ebp+0x18) "invalid identifier '")
12881     (write-slice-buffered *(ebp+0x18) %ecx)
12882     (write-buffered *(ebp+0x18) "'\n")
12883     (flush *(ebp+0x18))
12884     (stop *(ebp+0x1c) 1)
12885     # never gets here
12886 
12887 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)
12888     # pseudocode:
12889     #   stmt->name = slice-to-string(next-mu-token(line))
12890     #   while true
12891     #     name = next-mu-token(line)
12892     #     v = lookup-var-or-literal(name)
12893     #     stmt->inouts = append(v, stmt->inouts)
12894     #
12895     # . prologue
12896     55/push-ebp
12897     89/<- %ebp 4/r32/esp
12898     # . save registers
12899     50/push-eax
12900     51/push-ecx
12901     52/push-edx
12902     53/push-ebx
12903     56/push-esi
12904     57/push-edi
12905     # edi = stmt
12906     8b/-> *(ebp+8) 7/r32/edi
12907     # var name/ecx: slice
12908     68/push 0/imm32/end
12909     68/push 0/imm32/start
12910     89/<- %ecx 4/r32/esp
12911     # var is-deref?/edx: boolean = false
12912     ba/copy-to-edx 0/imm32/false
12913     # var v/esi: (handle var)
12914     68/push 0/imm32
12915     68/push 0/imm32
12916     89/<- %esi 4/r32/esp
12917 $add-operation-and-inputs-to-stmt:read-operation:
12918     (next-mu-token *(ebp+0xc) %ecx)
12919     8d/copy-address *(edi+4) 0/r32/eax  # Stmt1-operation or Regvardef-operationStmt1-operation or Regvardef-operation
12920     (slice-to-string Heap %ecx %eax)
12921     # var is-get?/ebx: boolean = (name == "get")
12922     (slice-equal? %ecx "get")  # => eax
12923     89/<- %ebx 0/r32/eax
12924     {
12925 $add-operation-and-inputs-to-stmt:read-inouts:
12926       # name = next-mu-token(line)
12927       (next-mu-token *(ebp+0xc) %ecx)
12928       # if slice-empty?(word-slice) break
12929       (slice-empty? %ecx)  # => eax
12930       3d/compare-eax-and 0/imm32/false
12931       0f 85/jump-if-!= break/disp32
12932       # if (name == "<-") abort
12933       (slice-equal? %ecx "<-")
12934       3d/compare-eax-and 0/imm32/false
12935       0f 85/jump-if-!= $add-operation-and-inputs-to-stmt:abort/disp32
12936       # if (is-get? && second operand) lookup or create offset
12937       {
12938         81 7/subop/compare %ebx 0/imm32/false
12939         74/jump-if-= break/disp8
12940         (lookup *(edi+0xc) *(edi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
12941         3d/compare-eax-and 0/imm32
12942         74/jump-if-= break/disp8
12943         (lookup-or-create-constant %eax %ecx %esi)
12944 #?         (lookup *esi *(esi+4))
12945 #?         (write-buffered Stderr "creating new output var ")
12946 #?         (write-int32-hex-buffered Stderr %eax)
12947 #?         (write-buffered Stderr " for field called ")
12948 #?         (write-slice-buffered Stderr %ecx)
12949 #?         (write-buffered Stderr "; var name ")
12950 #?         (lookup *eax *(eax+4))  # Var-name
12951 #?         (write-buffered Stderr %eax)
12952 #?         (write-buffered Stderr Newline)
12953 #?         (flush Stderr)
12954         e9/jump $add-operation-and-inputs-to-stmt:save-var/disp32
12955       }
12956       # is-deref? = false
12957       ba/copy-to-edx 0/imm32/false
12958       # if (slice-starts-with?(name, '*')) ++name->start and set is-deref?
12959       8b/-> *ecx 0/r32/eax  # Slice-start
12960       8a/copy-byte *eax 0/r32/AL
12961       81 4/subop/and %eax 0xff/imm32
12962       3d/compare-eax-and 0x2a/imm32/asterisk
12963       {
12964         75/jump-if-!= break/disp8
12965 $add-operation-and-inputs-to-stmt:inout-is-deref:
12966         ff 0/subop/increment *ecx
12967         ba/copy-to-edx 1/imm32/true
12968       }
12969       (lookup-var-or-literal %ecx *(ebp+0x10) %esi *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
12970 $add-operation-and-inputs-to-stmt:save-var:
12971       8d/copy-address *(edi+0xc) 0/r32/eax
12972       (append-stmt-var Heap  *esi *(esi+4)  *(edi+0xc) *(edi+0x10)  %edx  %eax)  # Stmt1-inouts or Regvardef-inouts
12973       #
12974       e9/jump loop/disp32
12975     }
12976 $add-operation-and-inputs-to-stmt:end:
12977     # . reclaim locals
12978     81 0/subop/add %esp 0x10/imm32
12979     # . restore registers
12980     5f/pop-to-edi
12981     5e/pop-to-esi
12982     5b/pop-to-ebx
12983     5a/pop-to-edx
12984     59/pop-to-ecx
12985     58/pop-to-eax
12986     # . epilogue
12987     89/<- %esp 5/r32/ebp
12988     5d/pop-to-ebp
12989     c3/return
12990 
12991 $add-operation-and-inputs-to-stmt:abort:
12992     # error("fn ___: invalid identifier in '" line "'\n")
12993     (write-buffered *(ebp+0x18) "fn ")
12994     8b/-> *(ebp+0x14) 0/r32/eax
12995     (lookup *eax *(eax+4))  # Function-name Function-name => eax
12996     (write-buffered *(ebp+0x18) %eax)
12997     (rewind-stream *(ebp+0xc))
12998     (write-buffered *(ebp+0x18) ": invalid identifier in '")
12999     (write-stream-data *(ebp+0x18) *(ebp+0xc))
13000     (write-buffered *(ebp+0x18) "'\n")
13001     (flush *(ebp+0x18))
13002     (stop *(ebp+0x1c) 1)
13003     # never gets here
13004 
13005 stmt-has-outputs?:  # line: (addr stream byte) -> result/eax: boolean
13006     # . prologue
13007     55/push-ebp
13008     89/<- %ebp 4/r32/esp
13009     # . save registers
13010     51/push-ecx
13011     # var word-slice/ecx: slice
13012     68/push 0/imm32/end
13013     68/push 0/imm32/start
13014     89/<- %ecx 4/r32/esp
13015     # result = false
13016     b8/copy-to-eax 0/imm32/false
13017     (rewind-stream *(ebp+8))
13018     {
13019       (next-mu-token *(ebp+8) %ecx)
13020       # if slice-empty?(word-slice) break
13021       (slice-empty? %ecx)
13022       3d/compare-eax-and 0/imm32/false
13023       b8/copy-to-eax 0/imm32/false/result  # restore result (if we're here it's still false)
13024       0f 85/jump-if-!= break/disp32
13025       # if slice-starts-with?(word-slice, '#') break
13026       # . eax = *word-slice->start
13027       8b/-> *ecx 0/r32/eax
13028       8a/copy-byte *eax 0/r32/AL
13029       81 4/subop/and %eax 0xff/imm32
13030       # . if (eax == '#') break
13031       3d/compare-eax-and 0x23/imm32/hash
13032       b8/copy-to-eax 0/imm32/false/result  # restore result (if we're here it's still false)
13033       0f 84/jump-if-= break/disp32
13034       # if slice-equal?(word-slice, '<-') return true
13035       (slice-equal? %ecx "<-")
13036       3d/compare-eax-and 0/imm32/false
13037       74/jump-if-= loop/disp8
13038       b8/copy-to-eax 1/imm32/true
13039     }
13040 $stmt-has-outputs:end:
13041     (rewind-stream *(ebp+8))
13042     # . reclaim locals
13043     81 0/subop/add %esp 8/imm32
13044     # . restore registers
13045     59/pop-to-ecx
13046     # . epilogue
13047     89/<- %esp 5/r32/ebp
13048     5d/pop-to-ebp
13049     c3/return
13050 
13051 # if 'name' starts with a digit, create a new literal var for it
13052 # otherwise return first 'name' from the top (back) of 'vars' and abort if not found
13053 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)
13054     # . prologue
13055     55/push-ebp
13056     89/<- %ebp 4/r32/esp
13057     # . save registers
13058     50/push-eax
13059     51/push-ecx
13060     56/push-esi
13061     # esi = name
13062     8b/-> *(ebp+8) 6/r32/esi
13063     # if slice-empty?(name) abort
13064     (slice-empty? %esi)  # => eax
13065     3d/compare-eax-and 0/imm32/false
13066     0f 85/jump-if-!= $lookup-var-or-literal:abort/disp32
13067     # var c/ecx: byte = *name->start
13068     8b/-> *esi 1/r32/ecx
13069     8a/copy-byte *ecx 1/r32/CL
13070     81 4/subop/and %ecx 0xff/imm32
13071     # if (is-decimal-digit?(c) || c == '-') return new var(name)
13072     {
13073       81 7/subop/compare %ecx 0x2d/imm32/dash
13074       74/jump-if-= $lookup-var-or-literal:literal/disp8
13075       (is-decimal-digit? %ecx)  # => eax
13076       3d/compare-eax-and 0/imm32/false
13077       74/jump-if-= break/disp8
13078 $lookup-var-or-literal:literal:
13079       (new-literal-integer Heap %esi *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
13080       eb/jump $lookup-var-or-literal:end/disp8
13081     }
13082     # else if (c == '"') return new var(name)
13083     {
13084       81 7/subop/compare %ecx 0x22/imm32/dquote
13085       75/jump-if-!= break/disp8
13086 $lookup-var-or-literal:literal-string:
13087       (new-literal Heap %esi *(ebp+0x10))
13088       eb/jump $lookup-var-or-literal:end/disp8
13089     }
13090     # otherwise return lookup-var(name, vars)
13091     {
13092 $lookup-var-or-literal:var:
13093       (lookup-var %esi *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
13094     }
13095 $lookup-var-or-literal:end:
13096     # . restore registers
13097     5e/pop-to-esi
13098     59/pop-to-ecx
13099     58/pop-to-eax
13100     # . epilogue
13101     89/<- %esp 5/r32/ebp
13102     5d/pop-to-ebp
13103     c3/return
13104 
13105 $lookup-var-or-literal:abort:
13106     (write-buffered *(ebp+0x18) "fn ")
13107     8b/-> *(ebp+0x14) 0/r32/eax
13108     (lookup *eax *(eax+4))  # Function-name Function-name => eax
13109     (write-buffered *(ebp+0x18) %eax)
13110     (write-buffered *(ebp+0x18) ": empty variable!")
13111     (flush *(ebp+0x18))
13112     (stop *(ebp+0x1c) 1)
13113     # never gets here
13114 
13115 # return first 'name' from the top (back) of 'vars' and abort if not found
13116 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)
13117     # . prologue
13118     55/push-ebp
13119     89/<- %ebp 4/r32/esp
13120     # . save registers
13121     50/push-eax
13122     #
13123     (lookup-var-helper *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
13124     # if (*out == 0) abort
13125     8b/-> *(ebp+0x10) 0/r32/eax
13126     81 7/subop/compare *eax 0/imm32
13127     74/jump-if-= $lookup-var:abort/disp8
13128 $lookup-var:end:
13129     # . restore registers
13130     58/pop-to-eax
13131     # . epilogue
13132     89/<- %esp 5/r32/ebp
13133     5d/pop-to-ebp
13134     c3/return
13135 
13136 $lookup-var:abort:
13137     (write-buffered *(ebp+0x18) "fn ")
13138     8b/-> *(ebp+0x14) 0/r32/eax
13139     (lookup *eax *(eax+4))  # Function-name Function-name => eax
13140     (write-buffered *(ebp+0x18) %eax)
13141     (write-buffered *(ebp+0x18) ": unknown variable '")
13142     (write-slice-buffered *(ebp+0x18) *(ebp+8))
13143     (write-buffered *(ebp+0x18) "'\n")
13144     (flush *(ebp+0x18))
13145     (stop *(ebp+0x1c) 1)
13146     # never gets here
13147 
13148 # return first 'name' from the top (back) of 'vars', and 0/null if not found
13149 # ensure that 'name' if in a register is the topmost variable in that register
13150 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)
13151     # pseudocode:
13152     #   var curr: (addr handle var) = &vars->data[vars->top - 12]
13153     #   var min = vars->data
13154     #   while curr >= min
13155     #     var v: (handle var) = *curr
13156     #     if v->name == name
13157     #       return
13158     #     curr -= 12
13159     #
13160     # . prologue
13161     55/push-ebp
13162     89/<- %ebp 4/r32/esp
13163     # . save registers
13164     50/push-eax
13165     51/push-ecx
13166     52/push-edx
13167     53/push-ebx
13168     56/push-esi
13169     57/push-edi
13170     # clear out
13171     (zero-out *(ebp+0x10) *Handle-size)
13172     # esi = vars
13173     8b/-> *(ebp+0xc) 6/r32/esi
13174     # ebx = vars->top
13175     8b/-> *esi 3/r32/ebx
13176     # if (vars->top > vars->size) abort
13177     3b/compare<- *(esi+4) 0/r32/eax
13178     0f 8f/jump-if-> $lookup-var-helper:error1/disp32
13179     # var min/edx: (addr handle var) = vars->data
13180     8d/copy-address *(esi+8) 2/r32/edx
13181     # var curr/ebx: (addr handle var) = &vars->data[vars->top - 12]
13182     8d/copy-address *(esi+ebx-4) 3/r32/ebx  # vars + 8 + vars->type - 12
13183     # var var-in-reg/edi: 16 addrs
13184     68/push 0/imm32
13185     68/push 0/imm32
13186     68/push 0/imm32
13187     68/push 0/imm32
13188     68/push 0/imm32
13189     68/push 0/imm32
13190     68/push 0/imm32
13191     68/push 0/imm32
13192     68/push 0/imm32
13193     68/push 0/imm32
13194     68/push 0/imm32
13195     68/push 0/imm32
13196     68/push 0/imm32
13197     68/push 0/imm32
13198     68/push 0/imm32
13199     68/push 0/imm32
13200     89/<- %edi 4/r32/esp
13201     {
13202 $lookup-var-helper:loop:
13203       # if (curr < min) return
13204       39/compare %ebx 2/r32/edx
13205       0f 82/jump-if-addr< break/disp32
13206       # var v/ecx: (addr var) = lookup(*curr)
13207       (lookup *ebx *(ebx+4))  # => eax
13208       89/<- %ecx 0/r32/eax
13209       # var vn/eax: (addr array byte) = lookup(v->name)
13210       (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
13211       # if (vn == name) return curr
13212       (slice-equal? *(ebp+8) %eax)  # => eax
13213       3d/compare-eax-and 0/imm32/false
13214       {
13215         74/jump-if-= break/disp8
13216 $lookup-var-helper:found:
13217         # var vr/eax: (addr array byte) = lookup(v->register)
13218         (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
13219         3d/compare-eax-and 0/imm32
13220         {
13221           74/jump-if-= break/disp8
13222 $lookup-var-helper:found-register:
13223           # var reg/eax: int = get(Registers, vr)
13224           (get Mu-registers-unique %eax 0xc "Mu-registers-unique")  # => eax
13225           8b/-> *eax 0/r32/eax
13226           # if (var-in-reg[reg]) error
13227           8b/-> *(edi+eax<<2) 0/r32/eax
13228           3d/compare-eax-and 0/imm32
13229           0f 85/jump-if-!= $lookup-var-helper:error2/disp32
13230         }
13231 $lookup-var-helper:return:
13232         # esi = out
13233         8b/-> *(ebp+0x10) 6/r32/esi
13234         # *out = *curr
13235         8b/-> *ebx 0/r32/eax
13236         89/<- *esi 0/r32/eax
13237         8b/-> *(ebx+4) 0/r32/eax
13238         89/<- *(esi+4) 0/r32/eax
13239         # return
13240         eb/jump $lookup-var-helper:end/disp8
13241       }
13242       # 'name' not yet found; update var-in-reg if v in register
13243       # . var vr/eax: (addr array byte) = lookup(v->register)
13244       (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
13245       # . if (vr == 0) continue
13246       3d/compare-eax-and 0/imm32
13247       74/jump-if-= $lookup-var-helper:continue/disp8
13248       # . var reg/eax: int = get(Registers, vr)
13249       (get Mu-registers-unique %eax 0xc "Mu-registers-unique")  # => eax
13250       8b/-> *eax 0/r32/eax
13251       # . var-in-reg[reg] = v
13252       89/<- *(edi+eax<<2) 1/r32/ecx
13253 $lookup-var-helper:continue:
13254       # curr -= 12
13255       81 5/subop/subtract %ebx 0xc/imm32
13256       e9/jump loop/disp32
13257     }
13258 $lookup-var-helper:end:
13259     # . reclaim locals
13260     81 0/subop/add %esp 0x40/imm32
13261     # . restore registers
13262     5f/pop-to-edi
13263     5e/pop-to-esi
13264     5b/pop-to-ebx
13265     5a/pop-to-edx
13266     59/pop-to-ecx
13267     58/pop-to-eax
13268     # . epilogue
13269     89/<- %esp 5/r32/ebp
13270     5d/pop-to-ebp
13271     c3/return
13272 
13273 $lookup-var-helper:error1:
13274     (write-buffered *(ebp+0x18) "fn ")
13275     8b/-> *(ebp+0x14) 0/r32/eax
13276     (lookup *eax *(eax+4))  # Function-name Function-name => eax
13277     (write-buffered *(ebp+0x18) %eax)
13278     (write-buffered *(ebp+0x18) ": malformed stack when looking up '")
13279     (write-slice-buffered *(ebp+0x18) *(ebp+8))
13280     (write-buffered *(ebp+0x18) "'\n")
13281     (flush *(ebp+0x18))
13282     (stop *(ebp+0x1c) 1)
13283     # never gets here
13284 
13285 $lookup-var-helper:error2:
13286     # eax contains the conflicting var at this point
13287     (write-buffered *(ebp+0x18) "fn ")
13288     50/push-eax
13289     8b/-> *(ebp+0x14) 0/r32/eax
13290     (lookup *eax *(eax+4))  # Function-name Function-name => eax
13291     (write-buffered *(ebp+0x18) %eax)
13292     58/pop-eax
13293     (write-buffered *(ebp+0x18) ": register ")
13294     50/push-eax
13295     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
13296     (write-buffered *(ebp+0x18) %eax)
13297     58/pop-to-eax
13298     (write-buffered *(ebp+0x18) " reads var '")
13299     (write-slice-buffered *(ebp+0x18) *(ebp+8))
13300     (write-buffered *(ebp+0x18) "' after writing var '")
13301     (lookup *eax *(eax+4))  # Var-name Var-name => eax
13302     (write-buffered *(ebp+0x18) %eax)
13303     (write-buffered *(ebp+0x18) "'\n")
13304     (flush *(ebp+0x18))
13305     (stop *(ebp+0x1c) 1)
13306     # never gets here
13307 
13308 dump-vars:  # vars: (addr stack live-var)
13309     # pseudocode:
13310     #   var curr: (addr handle var) = &vars->data[vars->top - 12]
13311     #   var min = vars->data
13312     #   while curr >= min
13313     #     var v: (handle var) = *curr
13314     #     print v
13315     #     curr -= 12
13316     #
13317     # . prologue
13318     55/push-ebp
13319     89/<- %ebp 4/r32/esp
13320     # . save registers
13321     52/push-edx
13322     53/push-ebx
13323     56/push-esi
13324     # esi = vars
13325     8b/-> *(ebp+8) 6/r32/esi
13326     # ebx = vars->top
13327     8b/-> *esi 3/r32/ebx
13328     # var min/edx: (addr handle var) = vars->data
13329     8d/copy-address *(esi+8) 2/r32/edx
13330     # var curr/ebx: (addr handle var) = &vars->data[vars->top - 12]
13331     8d/copy-address *(esi+ebx-4) 3/r32/ebx  # vars + 8 + vars->type - 12
13332     {
13333 $dump-vars:loop:
13334       # if (curr < min) return
13335       39/compare %ebx 2/r32/edx
13336       0f 82/jump-if-addr< break/disp32
13337       #
13338       (write-buffered Stderr "  var@")
13339       (dump-var 2 %ebx)
13340       # curr -= 12
13341       81 5/subop/subtract %ebx 0xc/imm32
13342       e9/jump loop/disp32
13343     }
13344 $dump-vars:end:
13345     # . restore registers
13346     5e/pop-to-esi
13347     5b/pop-to-ebx
13348     5a/pop-to-edx
13349     # . epilogue
13350     89/<- %esp 5/r32/ebp
13351     5d/pop-to-ebp
13352     c3/return
13353 
13354 == data
13355 # Like Registers, but no esp or ebp
13356 Mu-registers:  # (addr stream {(handle array byte), int})
13357   # a table is a stream
13358   0xa8/imm32/write
13359   0/imm32/read
13360   0xa8/imm32/length
13361   # data
13362   # general-purpose registers
13363   # it is perfectly ok to use fake alloc-ids -- as long as you never try to reclaim them
13364   0x11/imm32/alloc-id $Mu-register-eax/imm32 0/imm32
13365   0x11/imm32/alloc-id $Mu-register-ecx/imm32 1/imm32
13366   0x11/imm32/alloc-id $Mu-register-edx/imm32 2/imm32
13367   0x11/imm32/alloc-id $Mu-register-ebx/imm32 3/imm32
13368   0x11/imm32/alloc-id $Mu-register-esi/imm32 6/imm32
13369   0x11/imm32/alloc-id $Mu-register-edi/imm32 7/imm32
13370   # floating-point registers
13371   0x11/imm32/alloc-id $Mu-register-xmm0/imm32 0/imm32
13372   0x11/imm32/alloc-id $Mu-register-xmm1/imm32 1/imm32
13373   0x11/imm32/alloc-id $Mu-register-xmm2/imm32 2/imm32
13374   0x11/imm32/alloc-id $Mu-register-xmm3/imm32 3/imm32
13375   0x11/imm32/alloc-id $Mu-register-xmm4/imm32 4/imm32
13376   0x11/imm32/alloc-id $Mu-register-xmm5/imm32 5/imm32
13377   0x11/imm32/alloc-id $Mu-register-xmm6/imm32 6/imm32
13378   0x11/imm32/alloc-id $Mu-register-xmm7/imm32 7/imm32
13379 
13380 # Like Mu-registers, but with unique codes for integer and floating-point
13381 # registers.
13382 # Don't use this for code-generation, only for checking.
13383 Mu-registers-unique:  # (addr stream {(handle array byte), int})
13384   # a table is a stream
13385   0xa8/imm32/write
13386   0/imm32/read
13387   0xa8/imm32/length
13388   # data
13389   # general-purpose registers
13390   0x11/imm32/alloc-id $Mu-register-eax/imm32 0/imm32
13391   0x11/imm32/alloc-id $Mu-register-ecx/imm32 1/imm32
13392   0x11/imm32/alloc-id $Mu-register-edx/imm32 2/imm32
13393   0x11/imm32/alloc-id $Mu-register-ebx/imm32 3/imm32
13394   0x11/imm32/alloc-id $Mu-register-esi/imm32 6/imm32
13395   0x11/imm32/alloc-id $Mu-register-edi/imm32 7/imm32
13396   # floating-point registers
13397   0x11/imm32/alloc-id $Mu-register-xmm0/imm32 8/imm32
13398   0x11/imm32/alloc-id $Mu-register-xmm1/imm32 9/imm32
13399   0x11/imm32/alloc-id $Mu-register-xmm2/imm32 0xa/imm32
13400   0x11/imm32/alloc-id $Mu-register-xmm3/imm32 0xb/imm32
13401   0x11/imm32/alloc-id $Mu-register-xmm4/imm32 0xc/imm32
13402   0x11/imm32/alloc-id $Mu-register-xmm5/imm32 0xd/imm32
13403   0x11/imm32/alloc-id $Mu-register-xmm6/imm32 0xe/imm32
13404   0x11/imm32/alloc-id $Mu-register-xmm7/imm32 0xf/imm32
13405 
13406 $Mu-register-eax:
13407   0x11/imm32/alloc-id
13408   3/imm32/size
13409   0x65/e 0x61/a 0x78/x
13410 
13411 $Mu-register-ecx:
13412   0x11/imm32/alloc-id
13413   3/imm32/size
13414   0x65/e 0x63/c 0x78/x
13415 
13416 $Mu-register-edx:
13417   0x11/imm32/alloc-id
13418   3/imm32/size
13419   0x65/e 0x64/d 0x78/x
13420 
13421 $Mu-register-ebx:
13422   0x11/imm32/alloc-id
13423   3/imm32/size
13424   0x65/e 0x62/b 0x78/x
13425 
13426 $Mu-register-esi:
13427   0x11/imm32/alloc-id
13428   3/imm32/size
13429   0x65/e 0x73/s 0x69/i
13430 
13431 $Mu-register-edi:
13432   0x11/imm32/alloc-id
13433   3/imm32/size
13434   0x65/e 0x64/d 0x69/i
13435 
13436 $Mu-register-xmm0:
13437   0x11/imm32/alloc-id:fake:payload
13438   # "xmm0"
13439   0x4/imm32/size
13440   0x78/x 0x6d/m 0x6d/m 0x30/0
13441 
13442 $Mu-register-xmm1:
13443   0x11/imm32/alloc-id:fake:payload
13444   # "xmm1"
13445   0x4/imm32/size
13446   0x78/x 0x6d/m 0x6d/m 0x31/1
13447 
13448 $Mu-register-xmm2:
13449   0x11/imm32/alloc-id:fake:payload
13450   # "xmm2"
13451   0x4/imm32/size
13452   0x78/x 0x6d/m 0x6d/m 0x32/2
13453 
13454 $Mu-register-xmm3:
13455   0x11/imm32/alloc-id:fake:payload
13456   # "xmm3"
13457   0x4/imm32/size
13458   0x78/x 0x6d/m 0x6d/m 0x33/3
13459 
13460 $Mu-register-xmm4:
13461   0x11/imm32/alloc-id:fake:payload
13462   # "xmm4"
13463   0x4/imm32/size
13464   0x78/x 0x6d/m 0x6d/m 0x34/4
13465 
13466 $Mu-register-xmm5:
13467   0x11/imm32/alloc-id:fake:payload
13468   # "xmm5"
13469   0x4/imm32/size
13470   0x78/x 0x6d/m 0x6d/m 0x35/5
13471 
13472 $Mu-register-xmm6:
13473   0x11/imm32/alloc-id:fake:payload
13474   # "xmm6"
13475   0x4/imm32/size
13476   0x78/x 0x6d/m 0x6d/m 0x36/6
13477 
13478 $Mu-register-xmm7:
13479   0x11/imm32/alloc-id:fake:payload
13480   # "xmm7"
13481   0x4/imm32/size
13482   0x78/x 0x6d/m 0x6d/m 0x37/7
13483 
13484 == code
13485 
13486 # push 'out' to 'vars' if not already there; it's assumed to be a fn output
13487 maybe-define-var:  # out: (handle var), vars: (addr stack live-var)
13488     # . prologue
13489     55/push-ebp
13490     89/<- %ebp 4/r32/esp
13491     # . save registers
13492     50/push-eax
13493     # var out-addr/eax: (addr var)
13494     (lookup *(ebp+8) *(ebp+0xc))  # => eax
13495     #
13496     (binding-exists? %eax *(ebp+0x10))  # => eax
13497     3d/compare-eax-and 0/imm32/false
13498     75/jump-if-!= $maybe-define-var:end/disp8
13499     # otherwise update vars
13500     (push *(ebp+0x10) *(ebp+8))
13501     (push *(ebp+0x10) *(ebp+0xc))
13502     (push *(ebp+0x10) 0)  # 'out' is always a fn output; never spill it
13503 $maybe-define-var:end:
13504     # . restore registers
13505     58/pop-to-eax
13506     # . epilogue
13507     89/<- %esp 5/r32/ebp
13508     5d/pop-to-ebp
13509     c3/return
13510 
13511 # simpler version of lookup-var-helper
13512 binding-exists?:  # target: (addr var), vars: (addr stack live-var) -> result/eax: boolean
13513     # pseudocode:
13514     #   var curr: (addr handle var) = &vars->data[vars->top - 12]
13515     #   var min = vars->data
13516     #   while curr >= min
13517     #     var v: (handle var) = *curr
13518     #     if v->name == target->name
13519     #       return true
13520     #     curr -= 12
13521     #   return false
13522     #
13523     # . prologue
13524     55/push-ebp
13525     89/<- %ebp 4/r32/esp
13526     # . save registers
13527     51/push-ecx
13528     52/push-edx
13529     56/push-esi
13530     # var target-name/ecx: (addr array byte) = lookup(target->name)
13531     8b/-> *(ebp+8) 0/r32/eax
13532     (lookup *eax *(eax+4))  # Var-name Var-name => eax
13533     89/<- %ecx 0/r32/eax
13534     # esi = vars
13535     8b/-> *(ebp+0xc) 6/r32/esi
13536     # eax = vars->top
13537     8b/-> *esi 0/r32/eax
13538     # var min/edx: (addr handle var) = vars->data
13539     8d/copy-address *(esi+8) 2/r32/edx
13540     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
13541     8d/copy-address *(esi+eax-4) 6/r32/esi  # vars + 8 + vars->type - 12
13542     {
13543 $binding-exists?:loop:
13544       # if (curr < min) return
13545       39/compare %esi 2/r32/edx
13546       0f 82/jump-if-addr< break/disp32
13547       # var v/eax: (addr var) = lookup(*curr)
13548       (lookup *esi *(esi+4))  # => eax
13549       # var vn/eax: (addr array byte) = lookup(v->name)
13550       (lookup *eax *(eax+4))  # Var-name Var-name => eax
13551       # if (vn == target-name) return true
13552       (string-equal? %ecx %eax)  # => eax
13553       3d/compare-eax-and 0/imm32/false
13554       75/jump-if-!= $binding-exists?:end/disp8  # eax already contains true
13555       # curr -= 12
13556       81 5/subop/subtract %esi 0xc/imm32
13557       e9/jump loop/disp32
13558     }
13559     b8/copy-to-eax 0/imm32/false
13560 $binding-exists?:end:
13561     # . restore registers
13562     5e/pop-to-esi
13563     5a/pop-to-edx
13564     59/pop-to-ecx
13565     # . epilogue
13566     89/<- %esp 5/r32/ebp
13567     5d/pop-to-ebp
13568     c3/return
13569 
13570 test-parse-mu-stmt:
13571     # . prologue
13572     55/push-ebp
13573     89/<- %ebp 4/r32/esp
13574     # setup
13575     8b/-> *Primitive-type-ids 0/r32/eax
13576     89/<- *Type-id 0/r32/eax  # stream-write
13577     (clear-stream _test-input-stream)
13578     (write _test-input-stream "increment n\n")
13579     # var vars/ecx: (stack (addr var) 16)
13580     81 5/subop/subtract %esp 0xc0/imm32
13581     68/push 0xc0/imm32/size
13582     68/push 0/imm32/top
13583     89/<- %ecx 4/r32/esp
13584     (clear-stack %ecx)
13585     # var v/edx: (handle var)
13586     68/push 0/imm32
13587     68/push 0/imm32
13588     89/<- %edx 4/r32/esp
13589     # var s/eax: (handle array byte)
13590     68/push 0/imm32
13591     68/push 0/imm32
13592     89/<- %eax 4/r32/esp
13593     # v = new var("n")
13594     (copy-array Heap "n" %eax)
13595     (new-var Heap *eax *(eax+4) %edx)
13596     #
13597     (push %ecx *edx)
13598     (push %ecx *(edx+4))
13599     (push %ecx 0)
13600     # var out/eax: (handle stmt)
13601     68/push 0/imm32
13602     68/push 0/imm32
13603     89/<- %eax 4/r32/esp
13604     # convert
13605     (parse-mu-stmt _test-input-stream %ecx 0 %eax Stderr 0)
13606     # var out-addr/edx: (addr stmt) = lookup(*out)
13607     (lookup *eax *(eax+4))  # => eax
13608     89/<- %edx 0/r32/eax
13609     # out->tag
13610     (check-ints-equal *edx 1 "F - test-parse-mu-stmt/tag")  # Stmt-tag is Stmt1
13611     # out->operation
13612     (lookup *(edx+4) *(edx+8))  # Stmt1-operation Stmt1-operation => eax
13613     (check-strings-equal %eax "increment" "F - test-parse-mu-stmt/name")  # Stmt1-operation
13614     # out->inouts->value->name
13615     # . eax = out->inouts
13616     (lookup *(edx+0xc) *(edx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
13617     # . eax = out->inouts->value
13618     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
13619     # . eax = out->inouts->value->name
13620     (lookup *eax *(eax+4))  # Var-name Var-name => eax
13621     # .
13622     (check-strings-equal %eax "n" "F - test-parse-mu-stmt/inout:0")
13623     # . epilogue
13624     89/<- %esp 5/r32/ebp
13625     5d/pop-to-ebp
13626     c3/return
13627 
13628 test-parse-mu-stmt-with-comma:
13629     # . prologue
13630     55/push-ebp
13631     89/<- %ebp 4/r32/esp
13632     # setup
13633     8b/-> *Primitive-type-ids 0/r32/eax
13634     89/<- *Type-id 0/r32/eax  # stream-write
13635     (clear-stream _test-input-stream)
13636     (write _test-input-stream "copy-to n, 3\n")
13637     # var vars/ecx: (stack (addr var) 16)
13638     81 5/subop/subtract %esp 0xc0/imm32
13639     68/push 0xc0/imm32/size
13640     68/push 0/imm32/top
13641     89/<- %ecx 4/r32/esp
13642     (clear-stack %ecx)
13643     # var v/edx: (handle var)
13644     68/push 0/imm32
13645     68/push 0/imm32
13646     89/<- %edx 4/r32/esp
13647     # var s/eax: (handle array byte)
13648     68/push 0/imm32
13649     68/push 0/imm32
13650     89/<- %eax 4/r32/esp
13651     # v = new var("n")
13652     (copy-array Heap "n" %eax)
13653     (new-var Heap *eax *(eax+4) %edx)
13654     #
13655     (push %ecx *edx)
13656     (push %ecx *(edx+4))
13657     (push %ecx 0)
13658     # var out/eax: (handle stmt)
13659     68/push 0/imm32
13660     68/push 0/imm32
13661     89/<- %eax 4/r32/esp
13662     # convert
13663     (parse-mu-stmt _test-input-stream %ecx 0 %eax Stderr 0)
13664     # var out-addr/edx: (addr stmt) = lookup(*out)
13665     (lookup *eax *(eax+4))  # => eax
13666     89/<- %edx 0/r32/eax
13667     # out->tag
13668     (check-ints-equal *edx 1 "F - test-parse-mu-stmt-with-comma/tag")  # Stmt-tag is Stmt1
13669     # out->operation
13670     (lookup *(edx+4) *(edx+8))  # Stmt1-operation Stmt1-operation => eax
13671     (check-strings-equal %eax "copy-to" "F - test-parse-mu-stmt-with-comma/name")  # Stmt1-operation
13672     # out->inouts->value->name
13673     # . eax = out->inouts
13674     (lookup *(edx+0xc) *(edx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
13675     # . eax = out->inouts->value
13676     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
13677     # . eax = out->inouts->value->name
13678     (lookup *eax *(eax+4))  # Var-name Var-name => eax
13679     # .
13680     (check-strings-equal %eax "n" "F - test-parse-mu-stmt-with-comma/inout:0")
13681     # . epilogue
13682     89/<- %esp 5/r32/ebp
13683     5d/pop-to-ebp
13684     c3/return
13685 
13686 new-var:  # ad: (addr allocation-descriptor), name: (handle array byte), out: (addr handle var)
13687     # . prologue
13688     55/push-ebp
13689     89/<- %ebp 4/r32/esp
13690     # . save registers
13691     50/push-eax
13692     51/push-ecx
13693     # ecx = out
13694     8b/-> *(ebp+0x14) 1/r32/ecx
13695     #
13696     (allocate *(ebp+8) *Var-size %ecx)
13697     # var out-addr/eax: (addr var)
13698     (lookup *ecx *(ecx+4))  # => eax
13699     # out-addr->name = name
13700     8b/-> *(ebp+0xc) 1/r32/ecx
13701     89/<- *eax 1/r32/ecx  # Var-name
13702     8b/-> *(ebp+0x10) 1/r32/ecx
13703     89/<- *(eax+4) 1/r32/ecx  # Var-name
13704 #?     (write-buffered Stderr "var ")
13705 #?     (lookup *(ebp+0xc) *(ebp+0x10))
13706 #?     (write-buffered Stderr %eax)
13707 #?     (write-buffered Stderr " at ")
13708 #?     8b/-> *(ebp+0x14) 1/r32/ecx
13709 #?     (lookup *ecx *(ecx+4))  # => eax
13710 #?     (write-int32-hex-buffered Stderr %eax)
13711 #?     (write-buffered Stderr Newline)
13712 #?     (flush Stderr)
13713 $new-var:end:
13714     # . restore registers
13715     59/pop-to-ecx
13716     58/pop-to-eax
13717     # . epilogue
13718     89/<- %esp 5/r32/ebp
13719     5d/pop-to-ebp
13720     c3/return
13721 
13722 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)
13723     # . prologue
13724     55/push-ebp
13725     89/<- %ebp 4/r32/esp
13726     # . save registers
13727     50/push-eax
13728     51/push-ecx
13729     # if (!is-hex-int?(name)) abort
13730     (is-hex-int? *(ebp+0xc))  # => eax
13731     3d/compare-eax-and 0/imm32/false
13732     0f 84/jump-if-= $new-literal-integer:abort/disp32
13733     # a little more error-checking
13734     (check-mu-hex-int *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
13735     # out = new var(s)
13736     (new-var-from-slice *(ebp+8) *(ebp+0xc) *(ebp+0x10))
13737     # var out-addr/ecx: (addr var) = lookup(*out)
13738     8b/-> *(ebp+0x10) 0/r32/eax
13739     (lookup *eax *(eax+4))  # => eax
13740     89/<- %ecx 0/r32/eax
13741     # out-addr->block-depth = *Curr-block-depth
13742     8b/-> *Curr-block-depth 0/r32/eax
13743     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
13744     # out-addr->type = new tree()
13745     8d/copy-address *(ecx+8) 0/r32/eax  # Var-type
13746     (allocate *(ebp+8) *Type-tree-size %eax)
13747     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
13748     c7 0/subop/copy *eax 1/imm32/true  # Type-tree-is-atom
13749     # nothing else to do; default type is 'literal'
13750 $new-literal-integer:end:
13751     # . reclaim locals
13752     81 0/subop/add %esp 8/imm32
13753     # . restore registers
13754     59/pop-to-ecx
13755     58/pop-to-eax
13756     # . epilogue
13757     89/<- %esp 5/r32/ebp
13758     5d/pop-to-ebp
13759     c3/return
13760 
13761 $new-literal-integer:abort:
13762     (write-buffered *(ebp+0x18) "fn ")
13763     8b/-> *(ebp+0x14) 0/r32/eax
13764     (lookup *eax *(eax+4))  # Function-name Function-name => eax
13765     (write-buffered *(ebp+0x18) %eax)
13766     (write-buffered *(ebp+0x18) ": variable '")
13767     (write-slice-buffered *(ebp+0x18) *(ebp+0xc))
13768     (write-buffered *(ebp+0x18) "' cannot begin with a digit (or do you have a typo in a number?)\n")
13769     (flush *(ebp+0x18))
13770     (stop *(ebp+0x1c) 1)
13771     # never gets here
13772 
13773 # precondition: name is a valid hex integer; require a '0x' prefix
13774 check-mu-hex-int:  # name: (addr slice), err: (addr buffered-file), ed: (addr exit-descriptor)
13775     # . prologue
13776     55/push-ebp
13777     89/<- %ebp 4/r32/esp
13778     # . save registers
13779     50/push-eax
13780     51/push-ecx
13781     52/push-edx
13782     # ecx = name
13783     8b/-> *(ebp+8) 1/r32/ecx
13784     # var start/edx: (addr byte) = name->start
13785     8b/-> *ecx 2/r32/edx
13786     # if (*start == '-') ++start
13787     b8/copy-to-eax 0/imm32
13788     8a/copy-byte *edx 0/r32/AL
13789     3d/compare-eax-and 0x2d/imm32/dash
13790     {
13791       75/jump-if-!= break/disp8
13792       42/increment-edx
13793     }
13794     # var end/ecx: (addr byte) = name->end
13795     8b/-> *(ecx+4) 1/r32/ecx
13796     # var len/eax: int = name->end - name->start
13797     89/<- %eax 1/r32/ecx
13798     29/subtract-from %eax 2/r32/edx
13799     # if (len <= 1) return
13800     3d/compare-eax-with 1/imm32
13801     0f 8e/jump-if-<= $check-mu-hex-int:end/disp32
13802 $check-mu-hex-int:length->-1:
13803     # if slice-starts-with?({start, end}, "0x") return
13804     # . var tmp = {start, end}
13805     51/push-ecx
13806     52/push-edx
13807     89/<- %eax 4/r32/esp
13808     # .
13809     (slice-starts-with? %eax "0x")  # => eax
13810     # . reclaim tmp
13811     81 0/subop/add %esp 8/imm32
13812     # .
13813     3d/compare-eax-with 0/imm32/false
13814     75/jump-if-!= $check-mu-hex-int:end/disp8
13815 $check-mu-hex-int:abort:
13816     # otherwise abort
13817     (write-buffered *(ebp+0xc) "literal integers are always hex in Mu; start '")
13818     (write-slice-buffered *(ebp+0xc) *(ebp+8))
13819     (write-buffered *(ebp+0xc) "' with a '0x' to be unambiguous, converting it to hexadecimal as necessary.\n")
13820     (flush *(ebp+0xc))
13821     (stop *(ebp+0x10) 1)
13822 $check-mu-hex-int:end:
13823     # . restore registers
13824     5a/pop-to-edx
13825     59/pop-to-ecx
13826     58/pop-to-eax
13827     # . epilogue
13828     89/<- %esp 5/r32/ebp
13829     5d/pop-to-ebp
13830     c3/return
13831 
13832 new-literal:  # ad: (addr allocation-descriptor), name: (addr slice), out: (addr handle var)
13833     # . prologue
13834     55/push-ebp
13835     89/<- %ebp 4/r32/esp
13836     # . save registers
13837     50/push-eax
13838     51/push-ecx
13839     # var s/ecx: (handle array byte)
13840     68/push 0/imm32
13841     68/push 0/imm32
13842     89/<- %ecx 4/r32/esp
13843     # s = slice-to-string(name)
13844     (slice-to-string Heap *(ebp+0xc) %ecx)
13845     # allocate to out
13846     (new-var *(ebp+8) *ecx *(ecx+4) *(ebp+0x10))
13847     # var out-addr/ecx: (addr var) = lookup(*out)
13848     8b/-> *(ebp+0x10) 1/r32/ecx
13849     (lookup *ecx *(ecx+4))  # => eax
13850     89/<- %ecx 0/r32/eax
13851     # out-addr->block-depth = *Curr-block-depth
13852     8b/-> *Curr-block-depth 0/r32/eax
13853     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
13854     # out-addr->type/eax = new type
13855     8d/copy-address *(ecx+8) 0/r32/eax  # Var-type
13856     (allocate *(ebp+8) *Type-tree-size %eax)
13857     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
13858     # nothing else to do; default type is 'literal'
13859     c7 0/subop/copy *eax 1/imm32/true  # Type-tree-is-atom
13860 $new-literal:end:
13861     # . reclaim locals
13862     81 0/subop/add %esp 8/imm32
13863     # . restore registers
13864     59/pop-to-ecx
13865     58/pop-to-eax
13866     # . epilogue
13867     89/<- %esp 5/r32/ebp
13868     5d/pop-to-ebp
13869     c3/return
13870 
13871 new-var-from-slice:  # ad: (addr allocation-descriptor), name: (addr slice), out: (addr handle var)
13872     # . prologue
13873     55/push-ebp
13874     89/<- %ebp 4/r32/esp
13875     # . save registers
13876     51/push-ecx
13877     # var tmp/ecx: (handle array byte)
13878     68/push 0/imm32
13879     68/push 0/imm32
13880     89/<- %ecx 4/r32/esp
13881     # tmp = slice-to-string(name)
13882     (slice-to-string Heap *(ebp+0xc) %ecx)
13883     # out = new-var(tmp)
13884     (new-var *(ebp+8) *ecx *(ecx+4) *(ebp+0x10))
13885 $new-var-from-slice:end:
13886     # . reclaim locals
13887     81 0/subop/add %esp 8/imm32
13888     # . restore registers
13889     59/pop-to-ecx
13890     # . epilogue
13891     89/<- %esp 5/r32/ebp
13892     5d/pop-to-ebp
13893     c3/return
13894 
13895 new-var-def:  # ad: (addr allocation-descriptor), var: (handle var), out: (addr handle stmt)
13896     # . prologue
13897     55/push-ebp
13898     89/<- %ebp 4/r32/esp
13899     # . save registers
13900     50/push-eax
13901     51/push-ecx
13902     #
13903     (allocate *(ebp+8) *Stmt-size *(ebp+0x14))
13904     # var out-addr/eax: (addr stmt) = lookup(*out)
13905     8b/-> *(ebp+0x14) 0/r32/eax
13906     (lookup *eax *(eax+4))  # => eax
13907     # out-addr->tag = stmt
13908     c7 0/subop/copy *eax 2/imm32/tag/var-on-stack  # Stmt-tag
13909     # result->var = var
13910     8b/-> *(ebp+0xc) 1/r32/ecx
13911     89/<- *(eax+4) 1/r32/ecx  # Vardef-var
13912     8b/-> *(ebp+0x10) 1/r32/ecx
13913     89/<- *(eax+8) 1/r32/ecx  # Vardef-var
13914 $new-var-def:end:
13915     # . restore registers
13916     59/pop-to-ecx
13917     58/pop-to-eax
13918     # . epilogue
13919     89/<- %esp 5/r32/ebp
13920     5d/pop-to-ebp
13921     c3/return
13922 
13923 new-reg-var-def:  # ad: (addr allocation-descriptor), var: (handle var), out: (addr handle stmt)
13924     # . prologue
13925     55/push-ebp
13926     89/<- %ebp 4/r32/esp
13927     # . save registers
13928     50/push-eax
13929     # eax = out
13930     8b/-> *(ebp+0x14) 0/r32/eax
13931     #
13932     (allocate *(ebp+8) *Stmt-size %eax)
13933     # var out-addr/eax: (addr stmt) = lookup(*out)
13934     (lookup *eax *(eax+4))  # => eax
13935     # set tag
13936     c7 0/subop/copy *eax 3/imm32/tag/var-in-register  # Stmt-tag
13937     # set output
13938     8d/copy-address *(eax+0x14) 0/r32/eax  # Regvardef-outputs
13939     (append-stmt-var Heap  *(ebp+0xc) *(ebp+0x10)  0 0  0  %eax)
13940 $new-reg-var-def:end:
13941     # . restore registers
13942     58/pop-to-eax
13943     # . epilogue
13944     89/<- %esp 5/r32/ebp
13945     5d/pop-to-ebp
13946     c3/return
13947 
13948 append-list:  # ad: (addr allocation-descriptor), value: (handle _type), list: (handle list _type), out: (addr handle list _type)
13949     # . prologue
13950     55/push-ebp
13951     89/<- %ebp 4/r32/esp
13952     # . save registers
13953     50/push-eax
13954     51/push-ecx
13955     57/push-edi
13956     # edi = out
13957     8b/-> *(ebp+0x1c) 7/r32/edi
13958     # *out = new list
13959     (allocate *(ebp+8) *List-size %edi)
13960     # var out-addr/edi: (addr list _type) = lookup(*out)
13961     (lookup *edi *(edi+4))  # => eax
13962     89/<- %edi 0/r32/eax
13963     # out-addr->value = value
13964     8b/-> *(ebp+0xc) 0/r32/eax
13965     89/<- *edi 0/r32/eax  # List-value
13966     8b/-> *(ebp+0x10) 0/r32/eax
13967     89/<- *(edi+4) 0/r32/eax  # List-value
13968     # if (list == null) return
13969     81 7/subop/compare *(ebp+0x14) 0/imm32
13970     74/jump-if-= $append-list:end/disp8
13971     # otherwise append
13972 $append-list:non-empty-list:
13973     # var curr/eax: (addr list _type) = lookup(list)
13974     (lookup *(ebp+0x14) *(ebp+0x18))  # => eax
13975     # while (curr->next != null) curr = curr->next
13976     {
13977       81 7/subop/compare *(eax+8) 0/imm32  # List-next
13978       74/jump-if-= break/disp8
13979       # curr = lookup(curr->next)
13980       (lookup *(eax+8) *(eax+0xc))  # List-next, List-next => eax
13981       #
13982       eb/jump loop/disp8
13983     }
13984     # edi = out
13985     8b/-> *(ebp+0x1c) 7/r32/edi
13986     # curr->next = out
13987     8b/-> *edi 1/r32/ecx
13988     89/<- *(eax+8) 1/r32/ecx  # List-next
13989     8b/-> *(edi+4) 1/r32/ecx
13990     89/<- *(eax+0xc) 1/r32/ecx  # List-next
13991     # out = list
13992     8b/-> *(ebp+0x14) 1/r32/ecx
13993     89/<- *edi 1/r32/ecx
13994     8b/-> *(ebp+0x18) 1/r32/ecx
13995     89/<- *(edi+4) 1/r32/ecx
13996 $append-list:end:
13997     # . restore registers
13998     5f/pop-to-edi
13999     59/pop-to-ecx
14000     58/pop-to-eax
14001     # . epilogue
14002     89/<- %esp 5/r32/ebp
14003     5d/pop-to-ebp
14004     c3/return
14005 
14006 append-stmt-var:  # ad: (addr allocation-descriptor), v: (handle var), vars: (handle stmt-var), is-deref?: boolean, out: (addr handle stmt-var)
14007     # . prologue
14008     55/push-ebp
14009     89/<- %ebp 4/r32/esp
14010     # . save registers
14011     50/push-eax
14012     51/push-ecx
14013     57/push-edi
14014     # edi = out
14015     8b/-> *(ebp+0x20) 7/r32/edi
14016     # out = new stmt-var
14017     (allocate *(ebp+8) *Stmt-var-size %edi)
14018     # var out-addr/ecx: (addr stmt-var) = lookup(*out)
14019     (lookup *edi *(edi+4))  # => eax
14020     89/<- %ecx 0/r32/eax
14021     # out-addr->value = v
14022     8b/-> *(ebp+0xc) 0/r32/eax
14023     89/<- *ecx 0/r32/eax  # Stmt-var-value
14024     8b/-> *(ebp+0x10) 0/r32/eax
14025     89/<- *(ecx+4) 0/r32/eax  # Stmt-var-value
14026     # out-addr->is-deref? = is-deref?
14027     8b/-> *(ebp+0x1c) 0/r32/eax
14028     89/<- *(ecx+0x10) 0/r32/eax  # Stmt-var-is-deref
14029     # if (vars == null) return result
14030     81 7/subop/compare *(ebp+0x14) 0/imm32/null
14031     74/jump-if-= $append-stmt-var:end/disp8
14032     # otherwise append
14033     # var curr/eax: (addr stmt-var) = lookup(vars)
14034     (lookup *(ebp+0x14) *(ebp+0x18))  # => eax
14035     # while (curr->next != null) curr = curr->next
14036     {
14037       81 7/subop/compare *(eax+8) 0/imm32  # Stmt-var-next
14038       74/jump-if-= break/disp8
14039       # curr = lookup(curr->next)
14040       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next, Stmt-var-next => eax
14041       #
14042       eb/jump loop/disp8
14043     }
14044     # curr->next = out
14045     8b/-> *edi 1/r32/ecx
14046     89/<- *(eax+8) 1/r32/ecx  # Stmt-var-next
14047     8b/-> *(edi+4) 1/r32/ecx
14048     89/<- *(eax+0xc) 1/r32/ecx  # Stmt-var-next
14049     # out = vars
14050     8b/-> *(ebp+0x14) 1/r32/ecx
14051     89/<- *edi 1/r32/ecx
14052     8b/-> *(ebp+0x18) 1/r32/ecx
14053     89/<- *(edi+4) 1/r32/ecx
14054 $append-stmt-var:end:
14055     # . restore registers
14056     5f/pop-to-edi
14057     59/pop-to-ecx
14058     58/pop-to-eax
14059     # . epilogue
14060     89/<- %esp 5/r32/ebp
14061     5d/pop-to-ebp
14062     c3/return
14063 
14064 append-to-block:  # ad: (addr allocation-descriptor), block: (addr block), x: (handle stmt)
14065     # . prologue
14066     55/push-ebp
14067     89/<- %ebp 4/r32/esp
14068     # . save registers
14069     50/push-eax
14070     56/push-esi
14071     # esi = block
14072     8b/-> *(ebp+0xc) 6/r32/esi
14073     # block->stmts = append(x, block->stmts)
14074     8d/copy-address *(esi+4) 0/r32/eax  # Block-stmts
14075     (append-list *(ebp+8)  *(ebp+0x10) *(ebp+0x14)  *(esi+4) *(esi+8)  %eax)  # ad, x, x, Block-stmts, Block-stmts
14076 $append-to-block:end:
14077     # . restore registers
14078     5e/pop-to-esi
14079     58/pop-to-eax
14080     # . epilogue
14081     89/<- %esp 5/r32/ebp
14082     5d/pop-to-ebp
14083     c3/return
14084 
14085 ## Parsing types
14086 # We need to create metadata on user-defined types, and we need to use this
14087 # metadata as we parse instructions.
14088 # However, we also want to allow types to be used before their definitions.
14089 # This means we can't ever assume any type data structures exist.
14090 
14091 lookup-or-create-constant:  # container: (addr stmt-var), field-name: (addr slice), out: (addr handle var)
14092     # . prologue
14093     55/push-ebp
14094     89/<- %ebp 4/r32/esp
14095     # . save registers
14096     50/push-eax
14097     56/push-esi
14098     # var container-type/esi: type-id
14099     (container-type *(ebp+8))  # => eax
14100     89/<- %esi 0/r32/eax
14101     # var tmp/eax: (handle typeinfo) = find-or-create-typeinfo(container-type)
14102     68/push 0/imm32
14103     68/push 0/imm32
14104     89/<- %eax 4/r32/esp
14105     (find-or-create-typeinfo %esi %eax)
14106     # var tmp-addr/eax: (addr typeinfo) = lookup(tmp)
14107     (lookup *eax *(eax+4))  # => eax
14108     # result = find-or-create-typeinfo-output-var(typeinfo, field-name)
14109 #?     (write-buffered Stderr "constant: ")
14110 #?     (write-slice-buffered Stderr *(ebp+0xc))
14111 #?     (write-buffered Stderr Newline)
14112 #?     (flush Stderr)
14113     (find-or-create-typeinfo-output-var %eax *(ebp+0xc) *(ebp+0x10))
14114 #?     8b/-> *(ebp+0x10) 0/r32/eax
14115 #?     (write-buffered Stderr "@")
14116 #?     (lookup *eax *(eax+4))
14117 #?     (write-int32-hex-buffered Stderr %eax)
14118 #?     (lookup *eax *(eax+4))
14119 #?     (write-buffered Stderr %eax)
14120 #?     (write-buffered Stderr Newline)
14121 #?     (flush Stderr)
14122 #?     (write-buffered Stderr "offset: ")
14123 #?     8b/-> *(eax+0x14) 0/r32/eax
14124 #?     (write-int32-hex-buffered Stderr %eax)
14125 #?     (write-buffered Stderr Newline)
14126 #?     (flush Stderr)
14127 $lookup-or-create-constant:end:
14128     # . reclaim locals
14129     81 0/subop/add %esp 8/imm32
14130     # . restore registers
14131     5e/pop-to-esi
14132     58/pop-to-eax
14133     # . epilogue
14134     89/<- %esp 5/r32/ebp
14135     5d/pop-to-ebp
14136     c3/return
14137 
14138 # if addr var:
14139 #   container->var->type->right->left->value
14140 # otherwise
14141 #   container->var->type->value
14142 container-type:  # container: (addr stmt-var) -> result/eax: type-id
14143     # . prologue
14144     55/push-ebp
14145     89/<- %ebp 4/r32/esp
14146     #
14147     8b/-> *(ebp+8) 0/r32/eax
14148     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
14149     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
14150     {
14151       81 7/subop/compare *(eax+8) 0/imm32  # Type-tree-right
14152       74/jump-if-= break/disp8
14153       (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
14154       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
14155     }
14156     8b/-> *(eax+4) 0/r32/eax  # Type-tree-value
14157 $container-type:end:
14158     # . epilogue
14159     89/<- %esp 5/r32/ebp
14160     5d/pop-to-ebp
14161     c3/return
14162 
14163 is-container?:  # t: type-id -> result/eax: boolean
14164     # . prologue
14165     55/push-ebp
14166     89/<- %ebp 4/r32/esp
14167     #
14168     8b/-> *(ebp+8) 0/r32/eax
14169     c1/shift 4/subop/left %eax 2/imm8
14170     3b/compare 0/r32/eax *Primitive-type-ids
14171     0f 9d/set-if->= %al
14172     81 4/subop/and %eax 0xff/imm32
14173 $is-container?:end:
14174     # . epilogue
14175     89/<- %esp 5/r32/ebp
14176     5d/pop-to-ebp
14177     c3/return
14178 
14179 find-or-create-typeinfo:  # t: type-id, out: (addr handle typeinfo)
14180     # . prologue
14181     55/push-ebp
14182     89/<- %ebp 4/r32/esp
14183     # . save registers
14184     50/push-eax
14185     51/push-ecx
14186     52/push-edx
14187     57/push-edi
14188     # edi = out
14189     8b/-> *(ebp+0xc) 7/r32/edi
14190     # var fields/ecx: (handle table (handle array byte) (handle typeinfo-entry))
14191     68/push 0/imm32
14192     68/push 0/imm32
14193     89/<- %ecx 4/r32/esp
14194     # find-typeinfo(t, out)
14195     (find-typeinfo *(ebp+8) %edi)
14196     {
14197       # if (*out != 0) break
14198       81 7/subop/compare *edi 0/imm32
14199       0f 85/jump-if-!= break/disp32
14200 $find-or-create-typeinfo:create:
14201       # *out = allocate
14202       (allocate Heap *Typeinfo-size %edi)
14203       # var tmp/eax: (addr typeinfo) = lookup(*out)
14204       (lookup *edi *(edi+4))  # => eax
14205 #?     (write-buffered Stderr "created typeinfo at ")
14206 #?     (write-int32-hex-buffered Stderr %eax)
14207 #?     (write-buffered Stderr " for type-id ")
14208 #?     (write-int32-hex-buffered Stderr *(ebp+8))
14209 #?     (write-buffered Stderr Newline)
14210 #?     (flush Stderr)
14211       # tmp->id = t
14212       8b/-> *(ebp+8) 2/r32/edx
14213       89/<- *eax 2/r32/edx  # Typeinfo-id
14214       # tmp->fields = new table
14215       # . fields = new table
14216       (new-stream Heap 0x40 *Typeinfo-fields-row-size %ecx)
14217       # . tmp->fields = fields
14218       8b/-> *ecx 2/r32/edx
14219       89/<- *(eax+4) 2/r32/edx  # Typeinfo-fields
14220       8b/-> *(ecx+4) 2/r32/edx
14221       89/<- *(eax+8) 2/r32/edx  # Typeinfo-fields
14222       # tmp->next = Program->types
14223       8b/-> *_Program-types 1/r32/ecx
14224       89/<- *(eax+0x10) 1/r32/ecx  # Typeinfo-next
14225       8b/-> *_Program-types->payload 1/r32/ecx
14226       89/<- *(eax+0x14) 1/r32/ecx  # Typeinfo-next
14227       # Program->types = out
14228       8b/-> *edi 1/r32/ecx
14229       89/<- *_Program-types 1/r32/ecx
14230       8b/-> *(edi+4) 1/r32/ecx
14231       89/<- *_Program-types->payload 1/r32/ecx
14232     }
14233 $find-or-create-typeinfo:end:
14234     # . reclaim locals
14235     81 0/subop/add %esp 8/imm32
14236     # . restore registers
14237     5f/pop-to-edi
14238     5a/pop-to-edx
14239     59/pop-to-ecx
14240     58/pop-to-eax
14241     # . epilogue
14242     89/<- %esp 5/r32/ebp
14243     5d/pop-to-ebp
14244     c3/return
14245 
14246 find-typeinfo:  # t: type-id, out: (addr handle typeinfo)
14247     # . prologue
14248     55/push-ebp
14249     89/<- %ebp 4/r32/esp
14250     # . save registers
14251     50/push-eax
14252     51/push-ecx
14253     52/push-edx
14254     57/push-edi
14255     # ecx = t
14256     8b/-> *(ebp+8) 1/r32/ecx
14257     # edi = out
14258     8b/-> *(ebp+0xc) 7/r32/edi
14259     # *out = Program->types
14260     8b/-> *_Program-types 0/r32/eax
14261     89/<- *edi 0/r32/eax
14262     8b/-> *_Program-types->payload 0/r32/eax
14263     89/<- *(edi+4) 0/r32/eax
14264     {
14265 $find-typeinfo:loop:
14266       # if (*out == 0) break
14267       81 7/subop/compare *edi 0/imm32
14268       74/jump-if-= break/disp8
14269 $find-typeinfo:check:
14270       # var tmp/eax: (addr typeinfo) = lookup(*out)
14271       (lookup *edi *(edi+4))  # => eax
14272       # if (tmp->id == t) break
14273       39/compare *eax 1/r32/ecx  # Typeinfo-id
14274       74/jump-if-= break/disp8
14275 $find-typeinfo:continue:
14276       # *out = tmp->next
14277       8b/-> *(eax+0x10) 2/r32/edx  # Typeinfo-next
14278       89/<- *edi 2/r32/edx
14279       8b/-> *(eax+0x14) 2/r32/edx  # Typeinfo-next
14280       89/<- *(edi+4) 2/r32/edx
14281       #
14282       eb/jump loop/disp8
14283     }
14284 $find-typeinfo:end:
14285     # . restore registers
14286     5f/pop-to-edi
14287     5a/pop-to-edx
14288     59/pop-to-ecx
14289     58/pop-to-eax
14290     # . epilogue
14291     89/<- %esp 5/r32/ebp
14292     5d/pop-to-ebp
14293     c3/return
14294 
14295 find-or-create-typeinfo-output-var:  # T: (addr typeinfo), f: (addr slice), out: (addr handle var)
14296     # . prologue
14297     55/push-ebp
14298     89/<- %ebp 4/r32/esp
14299     # . save registers
14300     50/push-eax
14301     52/push-edx
14302     57/push-edi
14303     # var dest/edi: (handle typeinfo-entry)
14304     68/push 0/imm32
14305     68/push 0/imm32
14306     89/<- %edi 4/r32/esp
14307     # find-or-create-typeinfo-fields(T, f, dest)
14308     (find-or-create-typeinfo-fields *(ebp+8) *(ebp+0xc) %edi)
14309     # var dest-addr/edi: (addr typeinfo-entry) = lookup(dest)
14310     (lookup *edi *(edi+4))  # => eax
14311     89/<- %edi 0/r32/eax
14312     # if dest-addr->output-var doesn't exist, create it
14313     {
14314       81 7/subop/compare *(edi+0xc) 0/imm32  # Typeinfo-entry-output-var
14315       0f 85/jump-if-!= break/disp32
14316       # dest-addr->output-var = new var(dummy name, type, -1 offset)
14317       # . var name/eax: (handle array byte) = "field"
14318       68/push 0/imm32
14319       68/push 0/imm32
14320       89/<- %eax 4/r32/esp
14321       (slice-to-string Heap *(ebp+0xc) %eax)
14322       # . new var
14323       8d/copy-address *(edi+0xc) 2/r32/edx
14324       (new-var Heap  *eax *(eax+4)  %edx)
14325       # . reclaim name
14326       81 0/subop/add %esp 8/imm32
14327       # var result/edx: (addr var) = lookup(dest-addr->output-var)
14328       (lookup *(edi+0xc) *(edi+0x10))  # => eax
14329       89/<- %edx 0/r32/eax
14330       # result->type = new constant type
14331       8d/copy-address *(edx+8) 0/r32/eax  # Var-type
14332       (allocate Heap *Type-tree-size %eax)
14333       (lookup *(edx+8) *(edx+0xc))  # => eax
14334       c7 0/subop/copy *eax 1/imm32/true  # Type-tree-is-atom
14335       c7 0/subop/copy *(eax+4) 6/imm32/constant  # Type-tree-value
14336       c7 0/subop/copy *(eax+8) 0/imm32  # Type-tree-left
14337       c7 0/subop/copy *(eax+0xc) 0/imm32  # Type-tree-right
14338       c7 0/subop/copy *(eax+0x10) 0/imm32  # Type-tree-right
14339       # result->offset isn't filled out yet
14340       c7 0/subop/copy *(edx+0x14) -1/imm32/uninitialized  # Var-offset
14341     }
14342     # out = dest-addr->output-var
14343     8b/-> *(ebp+0x10) 2/r32/edx
14344     8b/-> *(edi+0xc) 0/r32/eax  # Typeinfo-entry-output-var
14345     89/<- *edx 0/r32/eax
14346     8b/-> *(edi+0x10) 0/r32/eax  # Typeinfo-entry-output-var
14347     89/<- *(edx+4) 0/r32/eax
14348 $find-or-create-typeinfo-output-var:end:
14349     # . reclaim locals
14350     81 0/subop/add %esp 8/imm32
14351     # . restore registers
14352     5f/pop-to-edi
14353     5a/pop-to-edx
14354     58/pop-to-eax
14355     # . epilogue
14356     89/<- %esp 5/r32/ebp
14357     5d/pop-to-ebp
14358     c3/return
14359 
14360 find-or-create-typeinfo-fields:  # T: (addr typeinfo), f: (addr slice), out: (addr handle typeinfo-entry)
14361     # . prologue
14362     55/push-ebp
14363     89/<- %ebp 4/r32/esp
14364     # . save registers
14365     50/push-eax
14366     56/push-esi
14367     57/push-edi
14368     # eax = lookup(T->fields)
14369     8b/-> *(ebp+8) 0/r32/eax
14370     (lookup *(eax+4) *(eax+8))  # Typeinfo-fields Typeinfo-fields => eax
14371     # edi = out
14372     8b/-> *(ebp+0x10) 7/r32/edi
14373     # var src/esi: (addr handle typeinfo-entry) = get-or-insert-slice(T->fields, f)
14374     (get-or-insert-slice %eax *(ebp+0xc) *Typeinfo-fields-row-size Heap)  # => eax
14375     89/<- %esi 0/r32/eax
14376     # if src doesn't exist, allocate it
14377     {
14378       81 7/subop/compare *esi 0/imm32
14379       75/jump-if-!= break/disp8
14380       (allocate Heap *Typeinfo-entry-size %esi)
14381 #?       (write-buffered Stderr "handle at ")
14382 #?       (write-int32-hex-buffered Stderr %esi)
14383 #?       (write-buffered Stderr ": ")
14384 #?       (write-int32-hex-buffered Stderr *esi)
14385 #?       (write-buffered Stderr " ")
14386 #?       (write-int32-hex-buffered Stderr *(esi+4))
14387 #?       (write-buffered Stderr Newline)
14388 #?       (flush Stderr)
14389 #?       (lookup *esi *(esi+4))
14390 #?       (write-buffered Stderr "created typeinfo fields at ")
14391 #?       (write-int32-hex-buffered Stderr %esi)
14392 #?       (write-buffered Stderr " for ")
14393 #?       (write-int32-hex-buffered Stderr *(ebp+8))
14394 #?       (write-buffered Stderr Newline)
14395 #?       (flush Stderr)
14396     }
14397     # *out = src
14398     # . *edi = *src
14399     8b/-> *esi 0/r32/eax
14400     89/<- *edi 0/r32/eax
14401     8b/-> *(esi+4) 0/r32/eax
14402     89/<- *(edi+4) 0/r32/eax
14403 $find-or-create-typeinfo-fields:end:
14404     # . restore registers
14405     5f/pop-to-edi
14406     5e/pop-to-esi
14407     58/pop-to-eax
14408     # . epilogue
14409     89/<- %esp 5/r32/ebp
14410     5d/pop-to-ebp
14411     c3/return
14412 
14413 populate-mu-type:  # in: (addr stream byte), t: (addr typeinfo), err: (addr buffered-file), ed: (addr exit-descriptor)
14414     # pseudocode:
14415     #   var line: (stream byte 512)
14416     #   curr-index = 0
14417     #   while true
14418     #     clear-stream(line)
14419     #     read-line-buffered(in, line)
14420     #     if line->write == 0
14421     #       abort
14422     #     word-slice = next-mu-token(line)
14423     #     if slice-empty?(word-slice)               # end of line
14424     #       continue
14425     #     if slice-equal?(word-slice, "}")
14426     #       break
14427     #     var v: (handle var) = parse-var-with-type(word-slice, line)
14428     #     var r: (handle typeinfo-fields) = find-or-create-typeinfo-fields(t, word-slice/v->name)
14429     #     TODO: ensure that r->first is null
14430     #     r->index = curr-index
14431     #     curr-index++
14432     #     r->input-var = v
14433     #     if r->output-var == 0
14434     #       r->output-var = new literal
14435     #     TODO: ensure nothing else in line
14436     # t->total-size-in-bytes = -2 (not yet initialized)
14437     #
14438     # . prologue
14439     55/push-ebp
14440     89/<- %ebp 4/r32/esp
14441     # var curr-index: int at *(ebp-4)
14442     68/push 0/imm32
14443     # . save registers
14444     50/push-eax
14445     51/push-ecx
14446     52/push-edx
14447     53/push-ebx
14448     56/push-esi
14449     57/push-edi
14450     # edi = t
14451     8b/-> *(ebp+0xc) 7/r32/edi
14452     # var line/ecx: (stream byte 512)
14453     81 5/subop/subtract %esp 0x200/imm32
14454     68/push 0x200/imm32/size
14455     68/push 0/imm32/read
14456     68/push 0/imm32/write
14457     89/<- %ecx 4/r32/esp
14458     # var word-slice/edx: slice
14459     68/push 0/imm32/end
14460     68/push 0/imm32/start
14461     89/<- %edx 4/r32/esp
14462     # var v/esi: (handle var)
14463     68/push 0/imm32
14464     68/push 0/imm32
14465     89/<- %esi 4/r32/esp
14466     # var r/ebx: (handle typeinfo-entry)
14467     68/push 0/imm32
14468     68/push 0/imm32
14469     89/<- %ebx 4/r32/esp
14470     {
14471 $populate-mu-type:line-loop:
14472       (clear-stream %ecx)
14473       (read-line-buffered *(ebp+8) %ecx)
14474       # if (line->write == 0) abort
14475       81 7/subop/compare *ecx 0/imm32
14476       0f 84/jump-if-= $populate-mu-type:error1/disp32
14477 +--  6 lines: #?       # dump line ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
14483       (next-mu-token %ecx %edx)
14484       # if slice-empty?(word-slice) continue
14485       (slice-empty? %edx)  # => eax
14486       3d/compare-eax-and 0/imm32
14487       0f 85/jump-if-!= loop/disp32
14488       # if slice-equal?(word-slice, "}") break
14489       (slice-equal? %edx "}")
14490       3d/compare-eax-and 0/imm32
14491       0f 85/jump-if-!= break/disp32
14492 $populate-mu-type:parse-element:
14493       # v = parse-var-with-type(word-slice, first-line)
14494       # must do this first to strip the trailing ':' from word-slice before
14495       # using it in find-or-create-typeinfo-fields below
14496       # TODO: clean up that mutation in parse-var-with-type
14497       (parse-var-with-type %edx %ecx %esi *(ebp+0x10) *(ebp+0x14))
14498       # if v is an addr, abort
14499       (lookup *esi *(esi+4))  # => eax
14500       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
14501       (is-mu-addr-type? %eax)  # => eax
14502       3d/compare-eax-and 0/imm32/false
14503       0f 85/jump-if-!= $populate-mu-type:error2/disp32
14504       # if v is an array, abort  (we could support it, but initialization gets complex)
14505       (lookup *esi *(esi+4))  # => eax
14506       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
14507       (is-mu-array-type? %eax)  # => eax
14508       3d/compare-eax-and 0/imm32/false
14509       0f 85/jump-if-!= $populate-mu-type:error3/disp32
14510       # if v is a byte, abort
14511       (lookup *esi *(esi+4))  # => eax
14512       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
14513       (is-simple-mu-type? %eax 8)  # byte => eax
14514       3d/compare-eax-and 0/imm32/false
14515       0f 85/jump-if-!= $populate-mu-type:error4/disp32
14516       # if v is a slice, abort
14517       (lookup *esi *(esi+4))  # => eax
14518       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
14519       (is-simple-mu-type? %eax 0xc)  # slice => eax
14520       3d/compare-eax-and 0/imm32/false
14521       0f 85/jump-if-!= $populate-mu-type:error5/disp32
14522       # if v is a stream, abort  (we could support it, but initialization gets even more complex)
14523       (lookup *esi *(esi+4))  # => eax
14524       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
14525       (is-mu-stream-type? %eax)  # => eax
14526       3d/compare-eax-and 0/imm32/false
14527       0f 85/jump-if-!= $populate-mu-type:error6/disp32
14528       # var tmp/ecx
14529       51/push-ecx
14530 $populate-mu-type:create-typeinfo-fields:
14531       # var r/ebx: (handle typeinfo-entry)
14532       (find-or-create-typeinfo-fields %edi %edx %ebx)
14533       # r->index = curr-index
14534       (lookup *ebx *(ebx+4))  # => eax
14535       8b/-> *(ebp-4) 1/r32/ecx
14536 #?       (write-buffered Stderr "saving index ")
14537 #?       (write-int32-hex-buffered Stderr %ecx)
14538 #?       (write-buffered Stderr " at ")
14539 #?       (write-int32-hex-buffered Stderr %edi)
14540 #?       (write-buffered Stderr Newline)
14541 #?       (flush Stderr)
14542       89/<- *(eax+8) 1/r32/ecx  # Typeinfo-entry-index
14543       # ++curr-index
14544       ff 0/subop/increment *(ebp-4)
14545 $populate-mu-type:set-input-type:
14546       # r->input-var = v
14547       8b/-> *esi 1/r32/ecx
14548       89/<- *eax 1/r32/ecx  # Typeinfo-entry-input-var
14549       8b/-> *(esi+4) 1/r32/ecx
14550       89/<- *(eax+4) 1/r32/ecx  # Typeinfo-entry-input-var
14551       # restore line
14552       59/pop-to-ecx
14553       {
14554 $populate-mu-type:create-output-type:
14555         # if (r->output-var == 0) create a new var with some placeholder data
14556         81 7/subop/compare *(eax+0xc) 0/imm32  # Typeinfo-entry-output-var
14557         75/jump-if-!= break/disp8
14558         8d/copy-address *(eax+0xc) 0/r32/eax  # Typeinfo-entry-output-var
14559         (new-literal Heap %edx %eax)
14560       }
14561       e9/jump loop/disp32
14562     }
14563 $populate-mu-type:invalidate-total-size-in-bytes:
14564     # Offsets and total size may not be accurate here since we may not yet
14565     # have encountered the element types.
14566     # We'll recompute them separately after parsing the entire program.
14567     c7 0/subop/copy *(edi+0xc) -2/imm32/uninitialized  # Typeinfo-total-size-in-bytes
14568 $populate-mu-type:end:
14569     # . reclaim locals
14570     81 0/subop/add %esp 0x224/imm32
14571     # . restore registers
14572     5f/pop-to-edi
14573     5e/pop-to-esi
14574     5b/pop-to-ebx
14575     5a/pop-to-edx
14576     59/pop-to-ecx
14577     58/pop-to-eax
14578     # reclaim curr-index
14579     81 0/subop/add %esp 4/imm32
14580     # . epilogue
14581     89/<- %esp 5/r32/ebp
14582     5d/pop-to-ebp
14583     c3/return
14584 
14585 $populate-mu-type:error1:
14586     # error("incomplete type definition '" t->name "'\n")
14587     (write-buffered *(ebp+0x10) "incomplete type definition '")
14588     (type-name *edi)  # Typeinfo-id => eax
14589     (write-buffered *(ebp+0x10) %eax)
14590     (write-buffered *(ebp+0x10) "\n")
14591     (flush *(ebp+0x10))
14592     (stop *(ebp+0x14) 1)
14593     # never gets here
14594 
14595 $populate-mu-type:error2:
14596     (write-buffered *(ebp+0x10) "type ")
14597     (type-name *edi)  # Typeinfo-id => eax
14598     (write-buffered *(ebp+0x10) %eax)
14599     (write-buffered *(ebp+0x10) ": 'addr' elements not allowed\n")
14600     (flush *(ebp+0x10))
14601     (stop *(ebp+0x14) 1)
14602     # never gets here
14603 
14604 $populate-mu-type:error3:
14605     (write-buffered *(ebp+0x10) "type ")
14606     (type-name *edi)  # Typeinfo-id => eax
14607     (write-buffered *(ebp+0x10) %eax)
14608     (write-buffered *(ebp+0x10) ": 'array' elements not allowed for now\n")
14609     (flush *(ebp+0x10))
14610     (stop *(ebp+0x14) 1)
14611     # never gets here
14612 
14613 $populate-mu-type:error4:
14614     (write-buffered *(ebp+0x10) "type ")
14615     (type-name *edi)  # Typeinfo-id => eax
14616     (write-buffered *(ebp+0x10) %eax)
14617     (write-buffered *(ebp+0x10) ": 'byte' elements not allowed\n")
14618     (flush *(ebp+0x10))
14619     (stop *(ebp+0x14) 1)
14620     # never gets here
14621 
14622 $populate-mu-type:error5:
14623     (write-buffered *(ebp+0x10) "type ")
14624     (type-name *edi)  # Typeinfo-id => eax
14625     (write-buffered *(ebp+0x10) %eax)
14626     (write-buffered *(ebp+0x10) ": 'slice' elements not allowed\n")
14627     (flush *(ebp+0x10))
14628     (stop *(ebp+0x14) 1)
14629     # never gets here
14630 
14631 $populate-mu-type:error6:
14632     (write-buffered *(ebp+0x10) "type ")
14633     (type-name *edi)  # Typeinfo-id => eax
14634     (write-buffered *(ebp+0x10) %eax)
14635     (write-buffered *(ebp+0x10) ": 'stream' elements not allowed for now\n")
14636     (flush *(ebp+0x10))
14637     (stop *(ebp+0x14) 1)
14638     # never gets here
14639 
14640 type-name:  # index: int -> result/eax: (addr array byte)
14641     # . prologue
14642     55/push-ebp
14643     89/<- %ebp 4/r32/esp
14644     #
14645     (index Type-id *(ebp+8))
14646 $type-name:end:
14647     # . epilogue
14648     89/<- %esp 5/r32/ebp
14649     5d/pop-to-ebp
14650     c3/return
14651 
14652 index:  # arr: (addr stream (handle array byte)), index: int -> result/eax: (addr array byte)
14653     # . prologue
14654     55/push-ebp
14655     89/<- %ebp 4/r32/esp
14656     # . save registers
14657     56/push-esi
14658     # TODO: bounds-check index
14659     # esi = arr
14660     8b/-> *(ebp+8) 6/r32/esi
14661     # eax = index
14662     8b/-> *(ebp+0xc) 0/r32/eax
14663     # eax = *(arr + 12 + index)
14664     8b/-> *(esi+eax<<2+0xc) 0/r32/eax
14665 $index:end:
14666     # . restore registers
14667     5e/pop-to-esi
14668     # . epilogue
14669     89/<- %esp 5/r32/ebp
14670     5d/pop-to-ebp
14671     c3/return
14672 
14673 #######################################################
14674 # Compute type sizes
14675 #######################################################
14676 
14677 # Compute the sizes of all user-defined types.
14678 # We'll need the sizes of their elements, which may be other user-defined
14679 # types, which we will compute as needed.
14680 
14681 # Initially, all user-defined types have their sizes set to -2 (invalid)
14682 populate-mu-type-sizes:  # err: (addr buffered-file), ed: (addr exit-descriptor)
14683     # . prologue
14684     55/push-ebp
14685     89/<- %ebp 4/r32/esp
14686 $populate-mu-type-sizes:total-sizes:
14687     # var curr/eax: (addr typeinfo) = lookup(Program->types)
14688     (lookup *_Program-types *_Program-types->payload)  # => eax
14689     {
14690       # if (curr == null) break
14691       3d/compare-eax-and 0/imm32/null
14692       74/jump-if-= break/disp8
14693       (populate-mu-type-sizes-in-type %eax *(ebp+8) *(ebp+0xc))
14694       # curr = lookup(curr->next)
14695       (lookup *(eax+0x10) *(eax+0x14))  # Typeinfo-next Typeinfo-next => eax
14696       eb/jump loop/disp8
14697     }
14698 $populate-mu-type-sizes:offsets:
14699     # curr = *Program->types
14700     (lookup *_Program-types *_Program-types->payload)  # => eax
14701     {
14702       # if (curr == null) break
14703       3d/compare-eax-and 0/imm32/null
14704       74/jump-if-= break/disp8
14705       (populate-mu-type-offsets %eax *(ebp+8) *(ebp+0xc))
14706       # curr = curr->next
14707       (lookup *(eax+0x10) *(eax+0x14))  # Typeinfo-next Typeinfo-next => eax
14708       eb/jump loop/disp8
14709     }
14710 $populate-mu-type-sizes:end:
14711     # . epilogue
14712     89/<- %esp 5/r32/ebp
14713     5d/pop-to-ebp
14714     c3/return
14715 
14716 # compute sizes of all fields, recursing as necessary
14717 # sum up all their sizes to arrive at total size
14718 # fields may be out of order, but that doesn't affect the answer
14719 populate-mu-type-sizes-in-type:  # T: (addr typeinfo), err: (addr buffered-file), ed: (addr exit-descriptor)
14720     # . prologue
14721     55/push-ebp
14722     89/<- %ebp 4/r32/esp
14723     # . save registers
14724     50/push-eax
14725     51/push-ecx
14726     52/push-edx
14727     56/push-esi
14728     57/push-edi
14729     # esi = T
14730     8b/-> *(ebp+8) 6/r32/esi
14731     # if T is already computed, return
14732     81 7/subop/compare *(esi+0xc) 0/imm32  # Typeinfo-total-size-in-bytes
14733     0f 8d/jump-if->= $populate-mu-type-sizes-in-type:end/disp32
14734     # if T is being computed, abort
14735     81 7/subop/compare *(esi+0xc) -1/imm32/being-computed  # Typeinfo-total-size-in-bytes
14736     0f 84/jump-if-= $populate-mu-type-sizes-in-type:abort/disp32
14737     # tag T (-2 to -1) to avoid infinite recursion
14738     c7 0/subop/copy *(esi+0xc) -1/imm32/being-computed  # Typeinfo-total-size-in-bytes
14739     # var total-size/edi: int = 0
14740     bf/copy-to-edi 0/imm32
14741     # - for every field, if it's a user-defined type, compute its size
14742     # var table/ecx: (addr table (handle array byte) (handle typeinfo-entry)) = lookup(T->fields)
14743     (lookup *(esi+4) *(esi+8))  # Typeinfo-fields Typeinfo-fields => eax
14744     89/<- %ecx 0/r32/eax
14745     # var table-size/edx: int = table->write
14746     8b/-> *ecx 2/r32/edx  # stream-write
14747     # var curr/ecx: (addr table_row) = table->data
14748     8d/copy-address *(ecx+0xc) 1/r32/ecx
14749     # var max/edx: (addr table_row) = table->data + table->write
14750     8d/copy-address *(ecx+edx) 2/r32/edx
14751     {
14752 $populate-mu-type-sizes-in-type:loop:
14753       # if (curr >= max) break
14754       39/compare %ecx 2/r32/edx
14755       73/jump-if-addr>= break/disp8
14756       # var t/eax: (addr typeinfo-entry) = lookup(curr->value)
14757       (lookup *(ecx+8) *(ecx+0xc))  # => eax
14758       # if (t->input-var == 0) silently ignore it; we'll emit a nice error message while type-checking
14759       81 7/subop/compare *eax 0/imm32  # Typeinfo-entry-input-var
14760       74/jump-if-= $populate-mu-type-sizes-in-type:end/disp8
14761       # compute size of t->input-var
14762       (lookup *eax *(eax+4))  # Typeinfo-entry-input-var Typeinfo-entry-input-var => eax
14763       (compute-size-of-var %eax *(ebp+0xc) *(ebp+0x10))  # => eax
14764       # result += eax
14765       01/add-to %edi 0/r32/eax
14766       # curr += row-size
14767       81 0/subop/add %ecx 0x10/imm32  # Typeinfo-fields-row-size
14768       #
14769       eb/jump loop/disp8
14770     }
14771     # - save result
14772     89/<- *(esi+0xc) 7/r32/edi  # Typeinfo-total-size-in-bytes
14773 $populate-mu-type-sizes-in-type:end:
14774     # . restore registers
14775     5f/pop-to-edi
14776     5e/pop-to-esi
14777     5a/pop-to-edx
14778     59/pop-to-ecx
14779     58/pop-to-eax
14780     # . epilogue
14781     89/<- %esp 5/r32/ebp
14782     5d/pop-to-ebp
14783     c3/return
14784 
14785 $populate-mu-type-sizes-in-type:abort:
14786     (write-buffered *(ebp+0xc) "cycle in type definitions\n")
14787     (flush *(ebp+0xc))
14788     (stop *(ebp+0x10) 1)
14789     # never gets here
14790 
14791 # Analogous to size-of, except we need to compute what size-of can just read
14792 # off the right data structures.
14793 compute-size-of-var:  # in: (addr var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
14794     # . prologue
14795     55/push-ebp
14796     89/<- %ebp 4/r32/esp
14797     # . push registers
14798     51/push-ecx
14799     # var t/ecx: (addr type-tree) = lookup(v->type)
14800     8b/-> *(ebp+8) 1/r32/ecx
14801     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
14802     89/<- %ecx 0/r32/eax
14803     # if (t->is-atom == false) t = lookup(t->left)
14804     {
14805       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
14806       75/jump-if-!= break/disp8
14807       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
14808       89/<- %ecx 0/r32/eax
14809     }
14810     # TODO: ensure t is an atom
14811     (compute-size-of-type-id *(ecx+4) *(ebp+0xc) *(ebp+0x10))  # Type-tree-value => eax
14812 $compute-size-of-var:end:
14813     # . restore registers
14814     59/pop-to-ecx
14815     # . epilogue
14816     89/<- %esp 5/r32/ebp
14817     5d/pop-to-ebp
14818     c3/return
14819 
14820 compute-size-of-type-id:  # t: type-id, err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
14821     # . prologue
14822     55/push-ebp
14823     89/<- %ebp 4/r32/esp
14824     # . save registers
14825     51/push-ecx
14826     # var out/ecx: (handle typeinfo)
14827     68/push 0/imm32
14828     68/push 0/imm32
14829     89/<- %ecx 4/r32/esp
14830     # eax = t
14831     8b/-> *(ebp+8) 0/r32/eax
14832     # if t is a literal, return 0
14833     3d/compare-eax-and 0/imm32/literal
14834     0f 84/jump-if-= $compute-size-of-type-id:end/disp32  # eax changes type from type-id to int
14835     # if t is a byte, return 4 (because we don't really support non-multiples of 4)
14836     3d/compare-eax-and 8/imm32/byte
14837     {
14838       75/jump-if-!= break/disp8
14839       b8/copy-to-eax 4/imm32
14840       eb/jump $compute-size-of-type-id:end/disp8
14841     }
14842     # if t is a handle, return 8
14843     3d/compare-eax-and 4/imm32/handle
14844     {
14845       75/jump-if-!= break/disp8
14846       b8/copy-to-eax 8/imm32
14847       eb/jump $compute-size-of-type-id:end/disp8  # eax changes type from type-id to int
14848     }
14849     # if t is a slice, return 8
14850     3d/compare-eax-and 0xc/imm32/slice
14851     {
14852       75/jump-if-!= break/disp8
14853       b8/copy-to-eax 8/imm32
14854       eb/jump $compute-size-of-type-id:end/disp8  # eax changes type from type-id to int
14855     }
14856     # if t is a user-defined type, compute its size
14857     # TODO: support non-atom type
14858     (find-typeinfo %eax %ecx)
14859     {
14860       81 7/subop/compare *ecx 0/imm32
14861       74/jump-if-= break/disp8
14862 $compute-size-of-type-id:user-defined:
14863       (lookup *ecx *(ecx+4))  # => eax
14864       (populate-mu-type-sizes-in-type %eax *(ebp+0xc) *(ebp+0x10))
14865       8b/-> *(eax+0xc) 0/r32/eax  # Typeinfo-total-size-in-bytes
14866       eb/jump $compute-size-of-type-id:end/disp8
14867     }
14868     # otherwise return the word size
14869     b8/copy-to-eax 4/imm32
14870 $compute-size-of-type-id:end:
14871     # . reclaim locals
14872     81 0/subop/add %esp 8/imm32
14873     # . restore registers
14874     59/pop-to-ecx
14875     # . epilogue
14876     89/<- %esp 5/r32/ebp
14877     5d/pop-to-ebp
14878     c3/return
14879 
14880 # at this point we have total sizes for all user-defined types
14881 # compute offsets for each element
14882 # complication: fields may be out of order
14883 populate-mu-type-offsets:  # in: (addr typeinfo), err: (addr buffered-file), ed: (addr exit-descriptor)
14884     # . prologue
14885     55/push-ebp
14886     89/<- %ebp 4/r32/esp
14887     # . save registers
14888     50/push-eax
14889     51/push-ecx
14890     52/push-edx
14891     53/push-ebx
14892     56/push-esi
14893     57/push-edi
14894 #?     (dump-typeinfos "aaa\n")
14895     # var curr-offset/edi: int = 0
14896     bf/copy-to-edi 0/imm32
14897     # var table/ecx: (addr table string_key (handle typeinfo-entry)) = lookup(in->fields)
14898     8b/-> *(ebp+8) 1/r32/ecx
14899     (lookup *(ecx+4) *(ecx+8))  # Typeinfo-fields Typeinfo-fields => eax
14900     89/<- %ecx 0/r32/eax
14901     # var num-elems/edx: int = table->write / Typeinfo-fields-row-size
14902     8b/-> *ecx 2/r32/edx  # stream-write
14903     c1 5/subop/shift-right-logical  %edx 4/imm8
14904     # var i/ebx: int = 0
14905     bb/copy-to-ebx 0/imm32
14906     {
14907 $populate-mu-type-offsets:loop:
14908       39/compare %ebx 2/r32/edx
14909       0f 8d/jump-if->= break/disp32
14910 #?       (write-buffered Stderr "looking up index ")
14911 #?       (write-int32-hex-buffered Stderr %ebx)
14912 #?       (write-buffered Stderr " in ")
14913 #?       (write-int32-hex-buffered Stderr *(ebp+8))
14914 #?       (write-buffered Stderr Newline)
14915 #?       (flush Stderr)
14916       # var v/esi: (addr typeinfo-entry)
14917       (locate-typeinfo-entry-with-index %ecx %ebx *(ebp+0xc) *(ebp+0x10))  # => eax
14918       89/<- %esi 0/r32/eax
14919       # if v is null, silently move on; we'll emit a nice error message while type-checking
14920       81 7/subop/compare %esi 0/imm32  # Typeinfo-entry-input-var
14921       74/jump-if-= $populate-mu-type-offsets:end/disp8
14922       # if (v->input-var == 0) silently ignore v; we'll emit a nice error message while type-checking
14923       81 7/subop/compare *esi 0/imm32  # Typeinfo-entry-input-var
14924       74/jump-if-= $populate-mu-type-offsets:end/disp8
14925       # v->output-var->offset = curr-offset
14926       # . eax: (addr var)
14927       (lookup *(esi+0xc) *(esi+0x10))  # Typeinfo-entry-output-var Typeinfo-entry-output-var => eax
14928       89/<- *(eax+0x14) 7/r32/edi  # Var-offset
14929       # curr-offset += size-of(v->input-var)
14930       (lookup *esi *(esi+4))  # Typeinfo-entry-input-var Typeinfo-entry-input-var => eax
14931       (size-of %eax)  # => eax
14932       01/add-to %edi 0/r32/eax
14933       # ++i
14934       43/increment-ebx
14935       e9/jump loop/disp32
14936     }
14937 $populate-mu-type-offsets:end:
14938     # . restore registers
14939     5f/pop-to-edi
14940     5e/pop-to-esi
14941     5b/pop-to-ebx
14942     5a/pop-to-edx
14943     59/pop-to-ecx
14944     58/pop-to-eax
14945     # . epilogue
14946     89/<- %esp 5/r32/ebp
14947     5d/pop-to-ebp
14948     c3/return
14949 
14950 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)
14951     # . prologue
14952     55/push-ebp
14953     89/<- %ebp 4/r32/esp
14954     # . save registers
14955     51/push-ecx
14956     52/push-edx
14957     53/push-ebx
14958     56/push-esi
14959     57/push-edi
14960     # esi = table
14961     8b/-> *(ebp+8) 6/r32/esi
14962     # var curr/ecx: (addr row (handle array byte) (handle typeinfo-entry)) = table->data
14963     8d/copy-address *(esi+0xc) 1/r32/ecx
14964     # var max/edx: (addr byte) = &table->data[table->write]
14965     8b/-> *esi 2/r32/edx
14966     8d/copy-address *(ecx+edx) 2/r32/edx
14967     {
14968 $locate-typeinfo-entry-with-index:loop:
14969       39/compare %ecx 2/r32/edx
14970       73/jump-if-addr>= break/disp8
14971       # var v/eax: (addr typeinfo-entry)
14972       (lookup *(ecx+8) *(ecx+0xc))  # => eax
14973       # if (v->index == idx) return v
14974       8b/-> *(eax+8) 3/r32/ebx  # Typeinfo-entry-index
14975 #?       (write-buffered Stderr "comparing ")
14976 #?       (write-int32-hex-buffered Stderr %ebx)
14977 #?       (write-buffered Stderr " and ")
14978 #?       (write-int32-hex-buffered Stderr *(ebp+0xc))
14979 #?       (write-buffered Stderr Newline)
14980 #?       (flush Stderr)
14981       39/compare *(ebp+0xc) 3/r32/ebx
14982       74/jump-if-= $locate-typeinfo-entry-with-index:end/disp8
14983       # curr += Typeinfo-entry-size
14984       81 0/subop/add %ecx 0x10/imm32  # Typeinfo-entry-size
14985       #
14986       eb/jump loop/disp8
14987     }
14988     # return 0
14989     b8/copy-to-eax 0/imm32
14990 $locate-typeinfo-entry-with-index:end:
14991 #?     (write-buffered Stderr "returning ")
14992 #?     (write-int32-hex-buffered Stderr %eax)
14993 #?     (write-buffered Stderr Newline)
14994 #?     (flush Stderr)
14995     # . restore registers
14996     5f/pop-to-edi
14997     5e/pop-to-esi
14998     5b/pop-to-ebx
14999     5a/pop-to-edx
15000     59/pop-to-ecx
15001     # . epilogue
15002     89/<- %esp 5/r32/ebp
15003     5d/pop-to-ebp
15004     c3/return
15005 
15006 dump-typeinfos:  # hdr: (addr array byte)
15007     # . prologue
15008     55/push-ebp
15009     89/<- %ebp 4/r32/esp
15010     # . save registers
15011     50/push-eax
15012     #
15013     (write-buffered Stderr *(ebp+8))
15014     (flush Stderr)
15015     # var curr/eax: (addr typeinfo) = lookup(Program->types)
15016     (lookup *_Program-types *_Program-types->payload)  # => eax
15017     {
15018       # if (curr == null) break
15019       3d/compare-eax-and 0/imm32
15020       74/jump-if-= break/disp8
15021       (write-buffered Stderr "---\n")
15022       (flush Stderr)
15023       (dump-typeinfo %eax)
15024       # curr = lookup(curr->next)
15025       (lookup *(eax+0x10) *(eax+0x14))  # Typeinfo-next Typeinfo-next => eax
15026       eb/jump loop/disp8
15027     }
15028 $dump-typeinfos:end:
15029     # . restore registers
15030     58/pop-to-eax
15031     # . epilogue
15032     89/<- %esp 5/r32/ebp
15033     5d/pop-to-ebp
15034     c3/return
15035 
15036 dump-typeinfo:  # in: (addr typeinfo)
15037     # . prologue
15038     55/push-ebp
15039     89/<- %ebp 4/r32/esp
15040     # . save registers
15041     50/push-eax
15042     51/push-ecx
15043     52/push-edx
15044     53/push-ebx
15045     56/push-esi
15046     57/push-edi
15047     # esi = in
15048     8b/-> *(ebp+8) 6/r32/esi
15049     # var table/ecx: (addr table (handle array byte) (handle typeinfo-entry)) = lookup(T->fields)
15050     (lookup *(esi+4) *(esi+8))  # Typeinfo-fields Typeinfo-fields => eax
15051     89/<- %ecx 0/r32/eax
15052     (write-buffered Stderr "id:")
15053     (write-int32-hex-buffered Stderr *esi)
15054     (write-buffered Stderr "\n")
15055     (write-buffered Stderr "fields @ ")
15056     (write-int32-hex-buffered Stderr %ecx)
15057     (write-buffered Stderr Newline)
15058     (flush Stderr)
15059     (write-buffered Stderr "  write: ")
15060     (write-int32-hex-buffered Stderr *ecx)
15061     (write-buffered Stderr Newline)
15062     (flush Stderr)
15063     (write-buffered Stderr "  read: ")
15064     (write-int32-hex-buffered Stderr *(ecx+4))
15065     (write-buffered Stderr Newline)
15066     (flush Stderr)
15067     (write-buffered Stderr "  size: ")
15068     (write-int32-hex-buffered Stderr *(ecx+8))
15069     (write-buffered Stderr Newline)
15070     (flush Stderr)
15071     # var table-size/edx: int = table->write
15072     8b/-> *ecx 2/r32/edx  # stream-write
15073     # var curr/ecx: (addr table_row) = table->data
15074     8d/copy-address *(ecx+0xc) 1/r32/ecx
15075     # var max/edx: (addr table_row) = table->data + table->write
15076     8d/copy-address *(ecx+edx) 2/r32/edx
15077     {
15078 $dump-typeinfo:loop:
15079       # if (curr >= max) break
15080       39/compare %ecx 2/r32/edx
15081       0f 83/jump-if-addr>= break/disp32
15082       (write-buffered Stderr "  row:\n")
15083       (write-buffered Stderr "    key: ")
15084       (write-int32-hex-buffered Stderr *ecx)
15085       (write-buffered Stderr ",")
15086       (write-int32-hex-buffered Stderr *(ecx+4))
15087       (write-buffered Stderr " = '")
15088       (lookup *ecx *(ecx+4))
15089       (write-buffered Stderr %eax)
15090       (write-buffered Stderr "' @ ")
15091       (write-int32-hex-buffered Stderr %eax)
15092       (write-buffered Stderr Newline)
15093       (flush Stderr)
15094       (write-buffered Stderr "    value: ")
15095       (write-int32-hex-buffered Stderr *(ecx+8))
15096       (write-buffered Stderr ",")
15097       (write-int32-hex-buffered Stderr *(ecx+0xc))
15098       (write-buffered Stderr " = typeinfo-entry@")
15099       (lookup *(ecx+8) *(ecx+0xc))
15100       (write-int32-hex-buffered Stderr %eax)
15101       (write-buffered Stderr Newline)
15102       (flush Stderr)
15103       (write-buffered Stderr "        input var@")
15104       (dump-var 5 %eax)
15105       (lookup *(ecx+8) *(ecx+0xc))
15106       (write-buffered Stderr "        index: ")
15107       (write-int32-hex-buffered Stderr *(eax+8))
15108       (write-buffered Stderr Newline)
15109       (flush Stderr)
15110       (write-buffered Stderr "        output var@")
15111       8d/copy-address *(eax+0xc) 0/r32/eax  # Typeinfo-entry-output-var
15112       (dump-var 5 %eax)
15113       (flush Stderr)
15114       # curr += row-size
15115       81 0/subop/add %ecx 0x10/imm32  # Typeinfo-fields-row-size
15116       #
15117       e9/jump loop/disp32
15118     }
15119 $dump-typeinfo:end:
15120     # . restore registers
15121     5f/pop-to-edi
15122     5e/pop-to-esi
15123     5b/pop-to-ebx
15124     5a/pop-to-edx
15125     59/pop-to-ecx
15126     58/pop-to-eax
15127     # . epilogue
15128     89/<- %esp 5/r32/ebp
15129     5d/pop-to-ebp
15130     c3/return
15131 
15132 dump-var:  # indent: int, v: (addr handle var)
15133     # . prologue
15134     55/push-ebp
15135     89/<- %ebp 4/r32/esp
15136     # . save registers
15137     50/push-eax
15138     53/push-ebx
15139     # eax = v
15140     8b/-> *(ebp+0xc) 0/r32/eax
15141     #
15142     (write-int32-hex-buffered Stderr *eax)
15143     (write-buffered Stderr ",")
15144     (write-int32-hex-buffered Stderr *(eax+4))
15145     (write-buffered Stderr "->")
15146     (lookup *eax *(eax+4))
15147     (write-int32-hex-buffered Stderr %eax)
15148     (write-buffered Stderr Newline)
15149     (flush Stderr)
15150     {
15151       3d/compare-eax-and 0/imm32
15152       0f 84/jump-if-= break/disp32
15153       (emit-indent Stderr *(ebp+8))
15154       (write-buffered Stderr "name: ")
15155       89/<- %ebx 0/r32/eax
15156       (write-int32-hex-buffered Stderr *ebx)  # Var-name
15157       (write-buffered Stderr ",")
15158       (write-int32-hex-buffered Stderr *(ebx+4))  # Var-name
15159       (write-buffered Stderr "->")
15160       (lookup *ebx *(ebx+4))  # Var-name
15161       (write-int32-hex-buffered Stderr %eax)
15162       {
15163         3d/compare-eax-and 0/imm32
15164         74/jump-if-= break/disp8
15165         (write-buffered Stderr Space)
15166         (write-buffered Stderr %eax)
15167       }
15168       (write-buffered Stderr Newline)
15169       (flush Stderr)
15170       (emit-indent Stderr *(ebp+8))
15171       (write-buffered Stderr "block depth: ")
15172       (write-int32-hex-buffered Stderr *(ebx+0x10))  # Var-block-depth
15173       (write-buffered Stderr Newline)
15174       (flush Stderr)
15175       (emit-indent Stderr *(ebp+8))
15176       (write-buffered Stderr "stack offset: ")
15177       (write-int32-hex-buffered Stderr *(ebx+0x14))  # Var-offset
15178       (write-buffered Stderr Newline)
15179       (flush Stderr)
15180       (emit-indent Stderr *(ebp+8))
15181       (write-buffered Stderr "reg: ")
15182       (write-int32-hex-buffered Stderr *(ebx+0x18))  # Var-register
15183       (write-buffered Stderr ",")
15184       (write-int32-hex-buffered Stderr *(ebx+0x1c))  # Var-register
15185       (write-buffered Stderr "->")
15186       (flush Stderr)
15187       (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register
15188       (write-int32-hex-buffered Stderr %eax)
15189       {
15190         3d/compare-eax-and 0/imm32
15191         74/jump-if-= break/disp8
15192         (write-buffered Stderr Space)
15193         (write-buffered Stderr %eax)
15194       }
15195       (write-buffered Stderr Newline)
15196       (flush Stderr)
15197     }
15198 $dump-var:end:
15199     # . restore registers
15200     5b/pop-to-ebx
15201     58/pop-to-eax
15202     # . epilogue
15203     89/<- %esp 5/r32/ebp
15204     5d/pop-to-ebp
15205     c3/return
15206 
15207 #######################################################
15208 # Type-checking
15209 #######################################################
15210 
15211 check-mu-types:  # err: (addr buffered-file), ed: (addr exit-descriptor)
15212     # . prologue
15213     55/push-ebp
15214     89/<- %ebp 4/r32/esp
15215     # . save registers
15216     50/push-eax
15217     # var curr/eax: (addr function) = lookup(Program->functions)
15218     (lookup *_Program-functions *_Program-functions->payload)  # => eax
15219     {
15220 $check-mu-types:loop:
15221       # if (curr == null) break
15222       3d/compare-eax-and 0/imm32
15223       0f 84/jump-if-= break/disp32
15224 +--  8 lines: #?       # dump curr->name ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
15232       (check-mu-function %eax *(ebp+8) *(ebp+0xc))
15233       # curr = lookup(curr->next)
15234       (lookup *(eax+0x20) *(eax+0x24))  # Function-next Function-next => eax
15235       e9/jump loop/disp32
15236     }
15237 $check-mu-types:end:
15238     # . restore registers
15239     58/pop-to-eax
15240     # . epilogue
15241     89/<- %esp 5/r32/ebp
15242     5d/pop-to-ebp
15243     c3/return
15244 
15245 check-mu-function:  # fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
15246     # . prologue
15247     55/push-ebp
15248     89/<- %ebp 4/r32/esp
15249     # . save registers
15250     50/push-eax
15251     # eax = f
15252     8b/-> *(ebp+8) 0/r32/eax
15253     # TODO: anything to check in header?
15254     # var body/eax: (addr block) = lookup(f->body)
15255     (lookup *(eax+0x18) *(eax+0x1c))  # Function-body Function-body => eax
15256     (check-mu-block %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10))
15257 $check-mu-function:end:
15258     # . restore registers
15259     58/pop-to-eax
15260     # . epilogue
15261     89/<- %esp 5/r32/ebp
15262     5d/pop-to-ebp
15263     c3/return
15264 
15265 check-mu-block:  # block: (addr block), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
15266     # . prologue
15267     55/push-ebp
15268     89/<- %ebp 4/r32/esp
15269     # . save registers
15270     50/push-eax
15271     # eax = block
15272     8b/-> *(ebp+8) 0/r32/eax
15273     # var stmts/eax: (addr list stmt) = lookup(block->statements)
15274     (lookup *(eax+4) *(eax+8))  # Block-stmts Block-stmts => eax
15275     #
15276     {
15277 $check-mu-block:check-empty:
15278       3d/compare-eax-and 0/imm32
15279       0f 84/jump-if-= break/disp32
15280       # emit block->statements
15281       (check-mu-stmt-list %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
15282     }
15283 $check-mu-block:end:
15284     # . restore registers
15285     58/pop-to-eax
15286     # . epilogue
15287     89/<- %esp 5/r32/ebp
15288     5d/pop-to-ebp
15289     c3/return
15290 
15291 check-mu-stmt-list:  # stmts: (addr list stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
15292     # . prologue
15293     55/push-ebp
15294     89/<- %ebp 4/r32/esp
15295     # . save registers
15296     50/push-eax
15297     56/push-esi
15298     # esi = stmts
15299     8b/-> *(ebp+8) 6/r32/esi
15300     {
15301 $check-mu-stmt-list:loop:
15302       81 7/subop/compare %esi 0/imm32
15303       0f 84/jump-if-= break/disp32
15304       # var curr-stmt/eax: (addr stmt) = lookup(stmts->value)
15305       (lookup *esi *(esi+4))  # List-value List-value => eax
15306       {
15307 $check-mu-stmt-list:check-for-block:
15308         81 7/subop/compare *eax 0/imm32/block  # Stmt-tag
15309         75/jump-if-!= break/disp8
15310 $check-mu-stmt-list:block:
15311         (check-mu-block %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
15312         eb/jump $check-mu-stmt-list:continue/disp8
15313       }
15314       {
15315 $check-mu-stmt-list:check-for-stmt1:
15316         81 7/subop/compare *eax 1/imm32/stmt1  # Stmt-tag
15317         0f 85/jump-if-!= break/disp32
15318 $check-mu-stmt-list:stmt1:
15319         (check-mu-stmt %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
15320         eb/jump $check-mu-stmt-list:continue/disp8
15321       }
15322       {
15323 $check-mu-stmt-list:check-for-reg-var-def:
15324         81 7/subop/compare *eax 3/imm32/reg-var-def  # Stmt-tag
15325         0f 85/jump-if-!= break/disp32
15326 $check-mu-stmt-list:reg-var-def:
15327         (check-mu-stmt %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
15328         eb/jump $check-mu-stmt-list:continue/disp8
15329       }
15330 $check-mu-stmt-list:continue:
15331       # TODO: raise an error on unrecognized Stmt-tag
15332       (lookup *(esi+8) *(esi+0xc))  # List-next List-next => eax
15333       89/<- %esi 0/r32/eax
15334       e9/jump loop/disp32
15335     }
15336 $check-mu-stmt-list:end:
15337     # . restore registers
15338     5e/pop-to-esi
15339     58/pop-to-eax
15340     # . epilogue
15341     89/<- %esp 5/r32/ebp
15342     5d/pop-to-ebp
15343     c3/return
15344 
15345 check-mu-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
15346     # . prologue
15347     55/push-ebp
15348     89/<- %ebp 4/r32/esp
15349     # . save registers
15350     50/push-eax
15351     # - if stmt's operation matches a primitive, check against it
15352     (has-primitive-name? *(ebp+8))  # => eax
15353     3d/compare-eax-and 0/imm32/false
15354     {
15355       74/jump-if-= break/disp8
15356       (check-mu-primitive *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
15357       e9/jump $check-mu-stmt:end/disp32
15358     }
15359     # - otherwise find a function to check against
15360     # var f/eax: (addr function) = lookup(*Program->functions)
15361     (lookup *_Program-functions *_Program-functions->payload)  # => eax
15362     (find-matching-function %eax *(ebp+8))  # => eax
15363     3d/compare-eax-and 0/imm32
15364     {
15365       74/jump-if-= break/disp8
15366       (check-mu-call *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
15367       eb/jump $check-mu-stmt:end/disp8
15368     }
15369     # var f/eax: (addr function) = lookup(*Program->signatures)
15370     (lookup *_Program-signatures *_Program-signatures->payload)  # => eax
15371     (find-matching-function %eax *(ebp+8))  # => eax
15372     3d/compare-eax-and 0/imm32
15373     {
15374       74/jump-if-= break/disp8
15375       (check-mu-call *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
15376       eb/jump $check-mu-stmt:end/disp8
15377     }
15378     # - otherwise abort
15379     e9/jump $check-mu-stmt:unknown-call/disp32
15380 $check-mu-stmt:end:
15381     # . restore registers
15382     58/pop-to-eax
15383     # . epilogue
15384     89/<- %esp 5/r32/ebp
15385     5d/pop-to-ebp
15386     c3/return
15387 
15388 $check-mu-stmt:unknown-call:
15389     (write-buffered *(ebp+0x10) "unknown function '")
15390     8b/-> *(ebp+8) 0/r32/eax
15391     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
15392     (write-buffered *(ebp+0x10) %eax)
15393     (write-buffered *(ebp+0x10) "'\n")
15394     (flush *(ebp+0x10))
15395     (stop *(ebp+0x14) 1)
15396     # never gets here
15397 
15398 has-primitive-name?:  # stmt: (addr stmt) -> result/eax: boolean
15399     # . prologue
15400     55/push-ebp
15401     89/<- %ebp 4/r32/esp
15402     # . save registers
15403     51/push-ecx
15404     56/push-esi
15405     # var name/esi: (addr array byte) = lookup(stmt->operation)
15406     8b/-> *(ebp+8) 6/r32/esi
15407     (lookup *(esi+4) *(esi+8))  # Stmt1-operation Stmt1-operation => eax
15408     89/<- %esi 0/r32/eax
15409     # if (name == "return") return true
15410     (string-equal? %esi "return")  # => eax
15411     3d/compare-eax-and 0/imm32/false
15412     0f 85/jump-if-!= $has-primitive-name?:end/disp32
15413     # if (name == "get") return true
15414     (string-equal? %esi "get")  # => eax
15415     3d/compare-eax-and 0/imm32/false
15416     0f 85/jump-if-!= $has-primitive-name?:end/disp32
15417     # if (name == "index") return true
15418     (string-equal? %esi "index")  # => eax
15419     3d/compare-eax-and 0/imm32/false
15420     0f 85/jump-if-!= $has-primitive-name?:end/disp32
15421     # if (name == "length") return true
15422     (string-equal? %esi "length")  # => eax
15423     3d/compare-eax-and 0/imm32/false
15424     0f 85/jump-if-!= $has-primitive-name?:end/disp32
15425     # if (name == "compute-offset") return true
15426     (string-equal? %esi "compute-offset")  # => eax
15427     3d/compare-eax-and 0/imm32/false
15428     0f 85/jump-if-!= $has-primitive-name?:end/disp32
15429     # if (name == "copy-object") return true
15430     (string-equal? %esi "copy-object")  # => eax
15431     3d/compare-eax-and 0/imm32/false
15432     0f 85/jump-if-!= $has-primitive-name?:end/disp32
15433     # if (name == "allocate") return true
15434     (string-equal? %esi "allocate")  # => eax
15435     3d/compare-eax-and 0/imm32/false
15436     0f 85/jump-if-!= $has-primitive-name?:end/disp32
15437     # if (name == "populate") return true
15438     (string-equal? %esi "populate")  # => eax
15439     3d/compare-eax-and 0/imm32/false
15440     0f 85/jump-if-!= $has-primitive-name?:end/disp32
15441     # if (name == "populate-stream") return true
15442     (string-equal? %esi "populate-stream")  # => eax
15443     3d/compare-eax-and 0/imm32/false
15444     0f 85/jump-if-!= $has-primitive-name?:end/disp32
15445     # if (name == "read-from-stream") return true
15446     (string-equal? %esi "read-from-stream")  # => eax
15447     3d/compare-eax-and 0/imm32/false
15448     0f 85/jump-if-!= $has-primitive-name?:end/disp32
15449     # if (name == "write-to-stream") return true
15450     (string-equal? %esi "write-to-stream")  # => eax
15451     3d/compare-eax-and 0/imm32/false
15452     0f 85/jump-if-!= $has-primitive-name?:end/disp32
15453     # var curr/ecx: (addr primitive) = Primitives
15454     b9/copy-to-ecx Primitives/imm32
15455     {
15456 $has-primitive-name?:loop:
15457       # if (curr == null) break
15458       81 7/subop/compare %ecx 0/imm32
15459       74/jump-if-= break/disp8
15460       # if (primitive->name == name) return true
15461       (lookup *ecx *(ecx+4))  # Primitive-name Primitive-name => eax
15462 #?       (write-buffered Stderr %eax)
15463 #?       (write-buffered Stderr Newline)
15464 #?       (flush Stderr)
15465       (string-equal? %esi %eax)  # => eax
15466       3d/compare-eax-and 0/imm32/false
15467       75/jump-if-!= $has-primitive-name?:end/disp8
15468 $has-primitive-name?:next-primitive:
15469       # curr = curr->next
15470       (lookup *(ecx+0x3c) *(ecx+0x40))  # Primitive-next Primitive-next => eax
15471       89/<- %ecx 0/r32/eax
15472       #
15473       e9/jump loop/disp32
15474     }
15475     # return null
15476     b8/copy-to-eax 0/imm32
15477 $has-primitive-name?:end:
15478     # . restore registers
15479     5e/pop-to-esi
15480     59/pop-to-ecx
15481     # . epilogue
15482     89/<- %esp 5/r32/ebp
15483     5d/pop-to-ebp
15484     c3/return
15485 
15486 check-mu-primitive:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
15487     # . prologue
15488     55/push-ebp
15489     89/<- %ebp 4/r32/esp
15490     # . save registers
15491     50/push-eax
15492     51/push-ecx
15493     # var op/ecx: (addr array byte) = lookup(stmt->operation)
15494     8b/-> *(ebp+8) 0/r32/eax
15495     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
15496     89/<- %ecx 0/r32/eax
15497     # if (op == "copy") check-mu-copy-stmt
15498     {
15499       (string-equal? %ecx "copy")  # => eax
15500       3d/compare-eax-and 0/imm32/false
15501       74/jump-if-= break/disp8
15502       (check-mu-copy-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
15503       e9/jump $check-mu-primitive:end/disp32
15504     }
15505     # if (op == "copy-to") check-mu-copy-to-stmt
15506     {
15507       (string-equal? %ecx "copy-to")  # => eax
15508       3d/compare-eax-and 0/imm32/false
15509       74/jump-if-= break/disp8
15510       (check-mu-copy-to-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
15511       e9/jump $check-mu-primitive:end/disp32
15512     }
15513     # if (op == "compare") check-mu-compare-stmt
15514     {
15515       (string-equal? %ecx "compare")  # => eax
15516       3d/compare-eax-and 0/imm32/false
15517       74/jump-if-= break/disp8
15518       (check-mu-compare-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
15519       e9/jump $check-mu-primitive:end/disp32
15520     }
15521     # if (op == "address") check-mu-address-stmt
15522     {
15523       (string-equal? %ecx "address")  # => eax
15524       3d/compare-eax-and 0/imm32/false
15525       74/jump-if-= break/disp8
15526       (check-mu-address-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
15527       e9/jump $check-mu-primitive:end/disp32
15528     }
15529     # if (op == "return") check-mu-return-stmt
15530     {
15531       (string-equal? %ecx "return")  # => eax
15532       3d/compare-eax-and 0/imm32/false
15533       74/jump-if-= break/disp8
15534       (check-mu-return-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
15535       e9/jump $check-mu-primitive:end/disp32
15536     }
15537     # if (op == "get") check-mu-get-stmt
15538     {
15539       (string-equal? %ecx "get")  # => eax
15540       3d/compare-eax-and 0/imm32/false
15541       74/jump-if-= break/disp8
15542       (check-mu-get-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
15543       e9/jump $check-mu-primitive:end/disp32
15544     }
15545     # if (op == "index") check-mu-index-stmt
15546     {
15547       (string-equal? %ecx "index")  # => eax
15548       3d/compare-eax-and 0/imm32/false
15549       74/jump-if-= break/disp8
15550       (check-mu-index-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
15551       e9/jump $check-mu-primitive:end/disp32
15552     }
15553     # if (op == "length") check-mu-length-stmt
15554     {
15555       (string-equal? %ecx "length")  # => eax
15556       3d/compare-eax-and 0/imm32/false
15557       74/jump-if-= break/disp8
15558       (check-mu-length-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
15559       e9/jump $check-mu-primitive:end/disp32
15560     }
15561     # if (op == "compute-offset") check-mu-compute-offset-stmt
15562     {
15563       (string-equal? %ecx "compute-offset")  # => eax
15564       3d/compare-eax-and 0/imm32/false
15565       74/jump-if-= break/disp8
15566       (check-mu-compute-offset-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
15567       e9/jump $check-mu-primitive:end/disp32
15568     }
15569     # if (op == "copy-object") check-mu-copy-object-stmt
15570     {
15571       (string-equal? %ecx "copy-object")  # => eax
15572       3d/compare-eax-and 0/imm32/false
15573       74/jump-if-= break/disp8
15574       (check-mu-copy-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
15575       e9/jump $check-mu-primitive:end/disp32
15576     }
15577     # if (op == "allocate") check-mu-allocate-stmt
15578     {
15579       (string-equal? %ecx "allocate")  # => eax
15580       3d/compare-eax-and 0/imm32/false
15581       74/jump-if-= break/disp8
15582       (check-mu-allocate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
15583       e9/jump $check-mu-primitive:end/disp32
15584     }
15585     # if (op == "populate") check-mu-populate-stmt
15586     {
15587       (string-equal? %ecx "populate")  # => eax
15588       3d/compare-eax-and 0/imm32/false
15589       74/jump-if-= break/disp8
15590       (check-mu-populate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
15591       e9/jump $check-mu-primitive:end/disp32
15592     }
15593     # if (op == "populate-stream") check-mu-populate-stream-stmt
15594     {
15595       (string-equal? %ecx "populate-stream")  # => eax
15596       3d/compare-eax-and 0/imm32/false
15597       74/jump-if-= break/disp8
15598       (check-mu-populate-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
15599       e9/jump $check-mu-primitive:end/disp32
15600     }
15601     # if (op == "read-from-stream") check-mu-read-from-stream-stmt
15602     {
15603       (string-equal? %ecx "read-from-stream")  # => eax
15604       3d/compare-eax-and 0/imm32/false
15605       74/jump-if-= break/disp8
15606       (check-mu-read-from-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
15607       e9/jump $check-mu-primitive:end/disp32
15608     }
15609     # if (op == "write-to-stream") check-mu-write-to-stream-stmt
15610     {
15611       (string-equal? %ecx "write-to-stream")  # => eax
15612       3d/compare-eax-and 0/imm32/false
15613       74/jump-if-= break/disp8
15614       (check-mu-write-to-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
15615       e9/jump $check-mu-primitive:end/disp32
15616     }
15617     # if (op == "convert") check-mu-convert-stmt
15618     {
15619       (string-equal? %ecx "convert")  # => eax
15620       3d/compare-eax-and 0/imm32/false
15621       74/jump-if-= break/disp8
15622       (check-mu-convert-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
15623       e9/jump $check-mu-primitive:end/disp32
15624     }
15625     # otherwise check-numberlike-stmt
15626     (check-mu-numberlike-primitive *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
15627 $check-mu-primitive:end:
15628     # . restore registers
15629     59/pop-to-ecx
15630     58/pop-to-eax
15631     # . epilogue
15632     89/<- %esp 5/r32/ebp
15633     5d/pop-to-ebp
15634     c3/return
15635 
15636 # by default, Mu primitives should only operate on 'number-like' types
15637 check-mu-numberlike-primitive:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
15638     # . prologue
15639     55/push-ebp
15640     89/<- %ebp 4/r32/esp
15641     # . save registers
15642     50/push-eax
15643     51/push-ecx
15644     56/push-esi
15645     # esi = stmt
15646     8b/-> *(ebp+8) 6/r32/esi
15647     # var gas/ecx: int = 2
15648     b9/copy-to-ecx 2/imm32
15649     # - check at most 1 output
15650     # var output/eax: (addr stmt-var) = stmt->outputs
15651     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
15652     {
15653       3d/compare-eax-and 0/imm32
15654       74/jump-if-= break/disp8
15655 $check-mu-numberlike-primitive:output:
15656       (check-mu-numberlike-output %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
15657       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
15658       3d/compare-eax-and 0/imm32
15659       0f 85/jump-if-!= $check-mu-numberlike-primitive:error-too-many-outputs/disp32
15660       # check output is in a register
15661       # --gas
15662       49/decrement-ecx
15663     }
15664     # - check first inout
15665     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
15666     {
15667       3d/compare-eax-and 0/imm32
15668       0f 84/jump-if-= $check-mu-numberlike-primitive:end/disp32
15669 $check-mu-numberlike-primitive:first-inout:
15670       (check-mu-numberlike-arg %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
15671       # --gas
15672       49/decrement-ecx
15673     }
15674     # - check second inout
15675     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
15676     {
15677       3d/compare-eax-and 0/imm32
15678       74/jump-if-= $check-mu-numberlike-primitive:end/disp8
15679 $check-mu-numberlike-primitive:second-inout:
15680       # is a second inout allowed?
15681       81 7/subop/compare %ecx 0/imm32
15682       0f 84/jump-if-= $check-mu-numberlike-primitive:error-too-many-inouts/disp32
15683 $check-mu-numberlike-primitive:second-inout-permitted:
15684       (check-mu-numberlike-arg %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
15685     }
15686 $check-mu-numberlike-primitive:third-inout:
15687     # if there's a third arg, raise an error
15688     81 7/subop/compare *(eax+8) 0/imm32  # Stmt-var-next
15689     0f 85/jump-if-!= $check-mu-numberlike-primitive:error-too-many-inouts/disp32
15690 $check-mu-numberlike-primitive:end:
15691     # . restore registers
15692     5e/pop-to-esi
15693     59/pop-to-ecx
15694     58/pop-to-eax
15695     # . epilogue
15696     89/<- %esp 5/r32/ebp
15697     5d/pop-to-ebp
15698     c3/return
15699 
15700 $check-mu-numberlike-primitive:error-too-many-inouts:
15701     (write-buffered *(ebp+0x10) "fn ")
15702     8b/-> *(ebp+0xc) 0/r32/eax
15703     (lookup *eax *(eax+4))  # Function-name Function-name => eax
15704     (write-buffered *(ebp+0x10) %eax)
15705     (write-buffered *(ebp+0x10) ": stmt ")
15706     (lookup *(esi+4) *(esi+8))  # Stmt1-operation Stmt1-operation => eax
15707     (write-buffered *(ebp+0x10) %eax)
15708     (write-buffered *(ebp+0x10) ": too many inouts; most primitives support at most two arguments, across inouts and outputs\n")
15709     (flush *(ebp+0x10))
15710     (stop *(ebp+0x14) 1)
15711     # never gets here
15712 
15713 $check-mu-numberlike-primitive:error-too-many-outputs:
15714     (write-buffered *(ebp+0x10) "fn ")
15715     8b/-> *(ebp+0xc) 0/r32/eax
15716     (lookup *eax *(eax+4))  # Function-name Function-name => eax
15717     (write-buffered *(ebp+0x10) %eax)
15718     (write-buffered *(ebp+0x10) ": stmt ")
15719     (lookup *(esi+4) *(esi+8))  # Stmt1-operation Stmt1-operation => eax
15720     (write-buffered *(ebp+0x10) %eax)
15721     (write-buffered *(ebp+0x10) ": too many outputs; most primitives support at most one output\n")
15722     (flush *(ebp+0x10))
15723     (stop *(ebp+0x14) 1)
15724     # never gets here
15725 
15726 check-mu-numberlike-arg:  # v: (addr stmt-var), stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
15727     # . prologue
15728     55/push-ebp
15729     89/<- %ebp 4/r32/esp
15730     # . save registers
15731     50/push-eax
15732     56/push-esi
15733     # var t/esi: (addr type-tree) = lookup(v->value->type)
15734     8b/-> *(ebp+8) 0/r32/eax
15735     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
15736     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
15737     89/<- %esi 0/r32/eax
15738 $check-mu-numberlike-arg:check-literal:
15739     # if t is an int, return
15740     (is-simple-mu-type? %esi 0)  # literal => eax
15741     3d/compare-eax-and 0/imm32/false
15742     75/jump-if-!= $check-mu-numberlike-arg:end/disp8
15743 $check-mu-numberlike-arg:check-addr:
15744     # if t is an addr and v is dereferenced, return
15745     {
15746       (is-mu-addr-type? %esi)  # => eax
15747       3d/compare-eax-and 0/imm32/false
15748       74/jump-if-= break/disp8
15749       8b/-> *(ebp+8) 0/r32/eax
15750       8b/-> *(eax+0x10) 0/r32/eax
15751       3d/compare-eax-and 0/imm32/false
15752       75/jump-if-!= $check-mu-numberlike-arg:end/disp8
15753     }
15754 $check-mu-numberlike-arg:output-checks:
15755     (check-mu-numberlike-output *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18))
15756 $check-mu-numberlike-arg:end:
15757     # . restore registers
15758     5e/pop-to-esi
15759     58/pop-to-eax
15760     # . epilogue
15761     89/<- %esp 5/r32/ebp
15762     5d/pop-to-ebp
15763     c3/return
15764 
15765 check-mu-numberlike-output:  # v: (addr stmt-var), stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
15766     # . prologue
15767     55/push-ebp
15768     89/<- %ebp 4/r32/esp
15769     # . save registers
15770     50/push-eax
15771     56/push-esi
15772     # var t/esi: (addr type-tree) = lookup(v->value->type)
15773     8b/-> *(ebp+8) 0/r32/eax
15774     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
15775     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
15776     89/<- %esi 0/r32/eax
15777 $check-mu-numberlike-output:check-int:
15778     # if t is an int, return
15779     (is-simple-mu-type? %esi 1)  # int => eax
15780     3d/compare-eax-and 0/imm32/false
15781     0f 85/jump-if-!= $check-mu-numberlike-output:end/disp32
15782 $check-mu-numberlike-output:check-float:
15783     # if t is a float, return
15784     (is-simple-mu-type? %esi 0xf)  # float => eax
15785     3d/compare-eax-and 0/imm32/false
15786     75/jump-if-!= $check-mu-numberlike-output:end/disp8
15787 $check-mu-numberlike-output:check-boolean:
15788     # if t is a boolean, return
15789     (is-simple-mu-type? %esi 5)  # boolean => eax
15790     3d/compare-eax-and 0/imm32/false
15791     75/jump-if-!= $check-mu-numberlike-output:end/disp8
15792 $check-mu-numberlike-output:check-byte:
15793     # if t is a byte, return
15794     (is-simple-mu-type? %esi 8)  # byte => eax
15795     3d/compare-eax-and 0/imm32/false
15796     75/jump-if-!= $check-mu-numberlike-output:end/disp8
15797 $check-mu-numberlike-output:check-code-point:
15798     # if t is a code-point, return
15799     (is-simple-mu-type? %esi 0xd)  # code-point => eax
15800     3d/compare-eax-and 0/imm32/false
15801     75/jump-if-!= $check-mu-numberlike-output:end/disp8
15802 $check-mu-numberlike-output:check-grapheme:
15803     # if t is a grapheme, return
15804     (is-simple-mu-type? %esi 0xe)  # grapheme => eax
15805     3d/compare-eax-and 0/imm32/false
15806     75/jump-if-!= $check-mu-numberlike-output:end/disp8
15807     e9/jump $check-mu-numberlike-output:fail/disp32
15808 $check-mu-numberlike-output:end:
15809     # . restore registers
15810     5e/pop-to-esi
15811     58/pop-to-eax
15812     # . epilogue
15813     89/<- %esp 5/r32/ebp
15814     5d/pop-to-ebp
15815     c3/return
15816 
15817 $check-mu-numberlike-output:fail:
15818     # otherwise raise an error
15819     (write-buffered *(ebp+0x14) "fn ")
15820     8b/-> *(ebp+0x10) 0/r32/eax
15821     (lookup *eax *(eax+4))  # Function-name Function-name => eax
15822     (write-buffered *(ebp+0x14) %eax)
15823     (write-buffered *(ebp+0x14) ": stmt ")
15824     8b/-> *(ebp+0xc) 0/r32/eax
15825     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
15826     (write-buffered *(ebp+0x14) %eax)
15827     (write-buffered *(ebp+0x14) ": only non-addr scalar args permitted\n")
15828     (flush *(ebp+0x14))
15829     (stop *(ebp+0x18) 1)
15830     # never gets here
15831 
15832 check-mu-copy-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
15833     # . prologue
15834     55/push-ebp
15835     89/<- %ebp 4/r32/esp
15836     # . save registers
15837 $check-mu-copy-stmt:end:
15838     # . restore registers
15839     # . epilogue
15840     89/<- %esp 5/r32/ebp
15841     5d/pop-to-ebp
15842     c3/return
15843 
15844 check-mu-copy-to-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
15845     # . prologue
15846     55/push-ebp
15847     89/<- %ebp 4/r32/esp
15848     # . save registers
15849 $check-mu-copy-to-stmt:end:
15850     # . restore registers
15851     # . epilogue
15852     89/<- %esp 5/r32/ebp
15853     5d/pop-to-ebp
15854     c3/return
15855 
15856 check-mu-compare-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
15857     # . prologue
15858     55/push-ebp
15859     89/<- %ebp 4/r32/esp
15860     # . save registers
15861 $check-mu-compare-stmt:end:
15862     # . restore registers
15863     # . epilogue
15864     89/<- %esp 5/r32/ebp
15865     5d/pop-to-ebp
15866     c3/return
15867 
15868 check-mu-address-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
15869     # . prologue
15870     55/push-ebp
15871     89/<- %ebp 4/r32/esp
15872     # . save registers
15873 $check-mu-address-stmt:end:
15874     # . restore registers
15875     # . epilogue
15876     89/<- %esp 5/r32/ebp
15877     5d/pop-to-ebp
15878     c3/return
15879 
15880 check-mu-return-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
15881     # . prologue
15882     55/push-ebp
15883     89/<- %ebp 4/r32/esp
15884     # . save registers
15885 $check-mu-return-stmt:end:
15886     # . restore registers
15887     # . epilogue
15888     89/<- %esp 5/r32/ebp
15889     5d/pop-to-ebp
15890     c3/return
15891 
15892 check-mu-get-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
15893     # . prologue
15894     55/push-ebp
15895     89/<- %ebp 4/r32/esp
15896     # . save registers
15897     50/push-eax
15898     51/push-ecx
15899     52/push-edx
15900     53/push-ebx
15901     56/push-esi
15902     57/push-edi
15903     # esi = stmt
15904     8b/-> *(ebp+8) 6/r32/esi
15905     # - check for 0 inouts
15906     # var base/ecx: (addr var) = stmt->inouts->value
15907     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
15908     3d/compare-eax-and 0/imm32/false
15909     0f 84/jump-if-= $check-mu-get-stmt:error-too-few-inouts/disp32
15910     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
15911     89/<- %ecx 0/r32/eax
15912 $check-mu-get-stmt:check-base:
15913     # - check base type
15914     # if it's an 'addr', check that it's in a register
15915     # var base-type/ebx: (addr type-tree) = lookup(base->type)
15916     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
15917     89/<- %ebx 0/r32/eax
15918     {
15919       81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
15920       0f 85/jump-if-!= break/disp32
15921 $check-mu-get-stmt:base-is-compound:
15922       # if (type->left != addr) break
15923       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
15924       (is-simple-mu-type? %eax 2)  # addr => eax
15925       3d/compare-eax-and 0/imm32/false
15926       74/jump-if-= break/disp8
15927 $check-mu-get-stmt:base-is-addr:
15928       # now check for register
15929       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
15930       0f 84/jump-if-= $check-mu-get-stmt:error-base-type-addr-but-not-register/disp32
15931 $check-mu-get-stmt:base-is-addr-in-register:
15932       # type->left is now an addr; skip it
15933       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
15934       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
15935       0f 85/jump-if-!= $check-mu-get-stmt:error-bad-base/disp32
15936 $check-mu-get-stmt:base-is-addr-to-atom-in-register:
15937       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
15938       89/<- %ebx 0/r32/eax
15939     }
15940 $check-mu-get-stmt:check-base-typeinfo:
15941     # ensure type is a container
15942     # var base-type-id/ebx: type-id = base-type->value
15943     8b/-> *(ebx+4) 3/r32/ebx  # Type-tree-value
15944     (is-container? %ebx)  # => eax
15945     3d/compare-eax-and 0/imm32/false
15946     0f 84/jump-if-= $check-mu-get-stmt:error-bad-base/disp32
15947     # var base-typeinfo/edx: (addr typeinfo) = find-typeinfo(base-type-id)
15948     # . var container/ecx: (handle typeinfo)
15949     68/push 0/imm32
15950     68/push 0/imm32
15951     89/<- %ecx 4/r32/esp
15952     # .
15953     (find-typeinfo %ebx %ecx)
15954     (lookup *ecx *(ecx+4))  # => eax
15955     # . reclaim container
15956     81 0/subop/add %esp 8/imm32
15957     # .
15958     89/<- %edx 0/r32/eax
15959     # var offset/ecx: (addr stmt-var) = stmt->inouts->next
15960     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
15961     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
15962     89/<- %ecx 0/r32/eax
15963     # - check for 1 inout
15964     3d/compare-eax-and 0/imm32/false
15965     0f 84/jump-if-= $check-mu-get-stmt:error-too-few-inouts/disp32
15966     # var offset/ecx: (addr var) = lookup(offset->value)
15967     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
15968     89/<- %ecx 0/r32/eax
15969     # - check for valid field
15970     81 7/subop/compare *(ecx+0x14) -1/imm32/uninitialized  # Var-offset
15971     0f 84/jump-if-= $check-mu-get-stmt:error-bad-field/disp32
15972     # - check for too many inouts
15973     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
15974     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
15975     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
15976     3d/compare-eax-and 0/imm32/false
15977     0f 85/jump-if-!= $check-mu-get-stmt:error-too-many-inouts/disp32
15978     # var output/edi: (addr var) = stmt->outputs->value
15979     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
15980     # - check for 0 outputs
15981     3d/compare-eax-and 0/imm32/false
15982     0f 84/jump-if-= $check-mu-get-stmt:error-too-few-outputs/disp32
15983     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
15984     89/<- %edi 0/r32/eax
15985 $check-mu-get-stmt:check-output-type:
15986     # - check output type
15987     # must be in register
15988     (lookup *(edi+0x18) *(edi+0x1c))  # Var-register Var-register => eax
15989     3d/compare-eax-and 0/imm32
15990     0f 84/jump-if-= $check-mu-get-stmt:error-output-not-in-register/disp32
15991     # must have a non-atomic type
15992     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
15993     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
15994     0f 85/jump-if-!= $check-mu-get-stmt:error-output-type-not-address/disp32
15995     # type must start with (addr ...)
15996     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
15997     (is-simple-mu-type? %eax 2)  # => eax
15998     3d/compare-eax-and 0/imm32/false
15999     0f 84/jump-if-= $check-mu-get-stmt:error-output-type-not-address/disp32
16000 $check-mu-get-stmt:check-output-type-match:
16001     # payload of addr type must match 'type' definition
16002     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
16003     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
16004     # if (payload->right == null) payload = payload->left
16005     81 7/subop/compare *(eax+0xc) 0/imm32/null  # Type-tree-right
16006     {
16007       75/jump-if-!= break/disp8
16008       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
16009     }
16010     89/<- %edi 0/r32/eax
16011     # . var output-name/ecx: (addr array byte)
16012     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
16013     89/<- %ecx 0/r32/eax
16014     # . var base-typeinfo-entry/eax: (addr handle typeinfo-entry)
16015     (lookup *(edx+4) *(edx+8))  # Typeinfo-fields Typeinfo-fields => eax
16016     (get %eax %ecx 0x10)  # => eax
16017     # .
16018     (lookup *eax *(eax+4))  # => eax
16019     (lookup *eax *(eax+4))  # Typeinfo-entry-input-var Typeinfo-entry-input-var => eax
16020     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
16021     # .
16022     (type-equal? %edi %eax)  # => eax
16023     3d/compare-eax-and 0/imm32/false
16024     0f 84/jump-if-= $check-mu-get-stmt:error-bad-output-type/disp32
16025     # - check for too many outputs
16026     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
16027     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
16028     3d/compare-eax-and 0/imm32/false
16029     0f 85/jump-if-!= $check-mu-get-stmt:error-too-many-outputs/disp32
16030 $check-mu-get-stmt:end:
16031     # . restore registers
16032     5f/pop-to-edi
16033     5e/pop-to-esi
16034     5b/pop-to-ebx
16035     5a/pop-to-edx
16036     59/pop-to-ecx
16037     58/pop-to-eax
16038     # . epilogue
16039     89/<- %esp 5/r32/ebp
16040     5d/pop-to-ebp
16041     c3/return
16042 
16043 $check-mu-get-stmt:error-too-few-inouts:
16044     (write-buffered *(ebp+0x10) "fn ")
16045     8b/-> *(ebp+0xc) 0/r32/eax
16046     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16047     (write-buffered *(ebp+0x10) %eax)
16048     (write-buffered *(ebp+0x10) ": stmt get: too few inouts (2 required)\n")
16049     (flush *(ebp+0x10))
16050     (stop *(ebp+0x14) 1)
16051     # never gets here
16052 
16053 $check-mu-get-stmt:error-too-many-inouts:
16054     (write-buffered *(ebp+0x10) "fn ")
16055     8b/-> *(ebp+0xc) 0/r32/eax
16056     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16057     (write-buffered *(ebp+0x10) %eax)
16058     (write-buffered *(ebp+0x10) ": stmt get: too many inouts (2 required)\n")
16059     (flush *(ebp+0x10))
16060     (stop *(ebp+0x14) 1)
16061     # never gets here
16062 
16063 $check-mu-get-stmt:error-too-few-outputs:
16064     (write-buffered *(ebp+0x10) "fn ")
16065     8b/-> *(ebp+0xc) 0/r32/eax
16066     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16067     (write-buffered *(ebp+0x10) %eax)
16068     (write-buffered *(ebp+0x10) ": stmt get: must have an output\n")
16069     (flush *(ebp+0x10))
16070     (stop *(ebp+0x14) 1)
16071     # never gets here
16072 
16073 $check-mu-get-stmt:error-too-many-outputs:
16074     (write-buffered *(ebp+0x10) "fn ")
16075     8b/-> *(ebp+0xc) 0/r32/eax
16076     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16077     (write-buffered *(ebp+0x10) %eax)
16078     (write-buffered *(ebp+0x10) ": stmt get: too many outputs (1 required)\n")
16079     (flush *(ebp+0x10))
16080     (stop *(ebp+0x14) 1)
16081     # never gets here
16082 
16083 $check-mu-get-stmt:error-bad-base:
16084     # error("fn " fn ": stmt get: var '" base->name "' must have a 'type' definition\n")
16085     (write-buffered *(ebp+0x10) "fn ")
16086     8b/-> *(ebp+0xc) 0/r32/eax
16087     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16088     (write-buffered *(ebp+0x10) %eax)
16089     (write-buffered *(ebp+0x10) ": stmt get: var '")
16090     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
16091     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
16092     (lookup *eax *(eax+4))  # Var-name Var-name => eax
16093     (write-buffered *(ebp+0x10) %eax)
16094     (write-buffered *(ebp+0x10) "' must have a 'type' definition\n")
16095     (flush *(ebp+0x10))
16096     (stop *(ebp+0x14) 1)
16097     # never gets here
16098 
16099 $check-mu-get-stmt:error-base-type-addr-but-not-register:
16100     (write-buffered *(ebp+0x10) "fn ")
16101     8b/-> *(ebp+0xc) 0/r32/eax
16102     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16103     (write-buffered *(ebp+0x10) %eax)
16104     (write-buffered *(ebp+0x10) ": stmt get: var '")
16105     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
16106     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
16107     (lookup *eax *(eax+4))  # Var-name Var-name => eax
16108     (write-buffered *(ebp+0x10) %eax)
16109     (write-buffered *(ebp+0x10) "' is an 'addr' type, and so must live in a register\n")
16110     (flush *(ebp+0x10))
16111     (stop *(ebp+0x14) 1)
16112     # never gets here
16113 
16114 $check-mu-get-stmt:error-bad-field:
16115     # error("fn " fn ": stmt get: type " type " has no member called '" curr->name "'\n")
16116     (write-buffered *(ebp+0x10) "fn ")
16117     8b/-> *(ebp+0xc) 0/r32/eax
16118     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16119     (write-buffered *(ebp+0x10) %eax)
16120     (write-buffered *(ebp+0x10) ": stmt get: type '")
16121     # . write(Type-id->data[tmp])
16122     bf/copy-to-edi Type-id/imm32
16123     (write-buffered *(ebp+0x10) *(edi+ebx<<2+0xc))
16124     # .
16125     (write-buffered *(ebp+0x10) "' has no member called '")
16126     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
16127     (write-buffered *(ebp+0x10) %eax)
16128     (write-buffered *(ebp+0x10) "'\n")
16129     (flush *(ebp+0x10))
16130     (stop *(ebp+0x14) 1)
16131     # never gets here
16132 
16133 $check-mu-get-stmt:error-output-not-in-register:
16134     (write-buffered *(ebp+0x10) "fn ")
16135     8b/-> *(ebp+0xc) 0/r32/eax
16136     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16137     (write-buffered *(ebp+0x10) %eax)
16138     (write-buffered *(ebp+0x10) ": stmt get: output '")
16139     (lookup *edi *(edi+4))  # Var-name Var-name => eax
16140     (write-buffered *(ebp+0x10) %eax)
16141     (write-buffered *(ebp+0x10) "' is not in a register\n")
16142     (flush *(ebp+0x10))
16143     (stop *(ebp+0x14) 1)
16144     # never gets here
16145 
16146 $check-mu-get-stmt:error-output-type-not-address:
16147     (write-buffered *(ebp+0x10) "fn ")
16148     8b/-> *(ebp+0xc) 0/r32/eax
16149     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16150     (write-buffered *(ebp+0x10) %eax)
16151     (write-buffered *(ebp+0x10) ": stmt get: output must be an addr\n")
16152     (flush *(ebp+0x10))
16153     (stop *(ebp+0x14) 1)
16154     # never gets here
16155 
16156 $check-mu-get-stmt:error-bad-output-type:
16157     (write-buffered *(ebp+0x10) "fn ")
16158     8b/-> *(ebp+0xc) 0/r32/eax
16159     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16160     (write-buffered *(ebp+0x10) %eax)
16161     (write-buffered *(ebp+0x10) ": stmt get: wrong output type for member '")
16162     (write-buffered *(ebp+0x10) %ecx)
16163     (write-buffered *(ebp+0x10) "' of type '")
16164     bf/copy-to-edi Type-id/imm32
16165     (write-buffered *(ebp+0x10) *(edi+ebx<<2+0xc))
16166     (write-buffered *(ebp+0x10) "'\n")
16167     (flush *(ebp+0x10))
16168     (stop *(ebp+0x14) 1)
16169     # never gets here
16170 
16171 check-mu-index-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
16172     # . prologue
16173     55/push-ebp
16174     89/<- %ebp 4/r32/esp
16175     # . save registers
16176     50/push-eax
16177     51/push-ecx
16178     52/push-edx
16179     53/push-ebx
16180     56/push-esi
16181     57/push-edi
16182     # esi = stmt
16183     8b/-> *(ebp+8) 6/r32/esi
16184     # - check for 0 inouts
16185     # var base/ecx: (addr var) = stmt->inouts->value
16186     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
16187 $check-mu-index-stmt:check-no-inouts:
16188     3d/compare-eax-and 0/imm32
16189     0f 84/jump-if-= $check-mu-index-stmt:error-too-few-inouts/disp32
16190     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
16191     89/<- %ecx 0/r32/eax
16192     # - check base type is either (addr array ...) in register or (array ...) on stack
16193     # var base-type/ebx: (addr type-tree) = lookup(base->type)
16194     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
16195     89/<- %ebx 0/r32/eax
16196     # if base-type is an atom, abort with a precise error
16197     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
16198     {
16199       74/jump-if-= break/disp8
16200       (is-simple-mu-type? %ebx 3)  # array => eax
16201       3d/compare-eax-and 0/imm32/false
16202       0f 85/jump-if-!= $check-mu-index-stmt:error-base-array-atom-type/disp32
16203       0f 84/jump-if-= $check-mu-index-stmt:error-base-non-array-type/disp32
16204     }
16205 $check-mu-index-stmt:base-is-compound:
16206     # if type->left not addr or array, abort
16207     {
16208       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
16209       (is-simple-mu-type? %eax 2)  # addr => eax
16210       3d/compare-eax-and 0/imm32/false
16211       75/jump-if-!= break/disp8
16212       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
16213       (is-simple-mu-type? %eax 3)  # array => eax
16214       3d/compare-eax-and 0/imm32/false
16215       75/jump-if-!= break/disp8
16216       e9/jump $check-mu-index-stmt:error-base-non-array-type/disp32
16217     }
16218     # if (type->left == addr) ensure type->right->left == array and type->register exists
16219     {
16220       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
16221       (is-simple-mu-type? %eax 2)  # addr => eax
16222       3d/compare-eax-and 0/imm32/false
16223       74/jump-if-= break/disp8
16224 $check-mu-index-stmt:base-is-addr:
16225       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
16226       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
16227       (is-simple-mu-type? %eax 3)  # array => eax
16228       3d/compare-eax-and 0/imm32/false
16229       0f 84/jump-if-= $check-mu-index-stmt:error-base-non-array-type/disp32
16230 $check-mu-index-stmt:check-base-addr-is-register:
16231       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
16232       0f 84/jump-if-= $check-mu-index-stmt:error-base-address-array-type-on-stack/disp32
16233     }
16234     # if (type->left == array) ensure type->register doesn't exist
16235     {
16236       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
16237       (is-simple-mu-type? %eax 3)  # array => eax
16238       3d/compare-eax-and 0/imm32/false
16239       74/jump-if-= break/disp8
16240 $check-mu-index-stmt:base-is-array:
16241       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
16242       0f 85/jump-if-!= $check-mu-index-stmt:error-base-array-type-in-register/disp32
16243     }
16244     # if (base-type->left == addr) base-type = base-type->right
16245     {
16246       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
16247       (is-simple-mu-type? %eax 2)  # addr => eax
16248       3d/compare-eax-and 0/imm32/false
16249       74/jump-if-= break/disp8
16250       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
16251       89/<- %ebx 0/r32/eax
16252     }
16253     # - check for 1 inout
16254     # var index/ecx: (addr stmt-var) = stmt->inouts->next->value
16255     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
16256     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
16257 $check-mu-index-stmt:check-single-inout:
16258     3d/compare-eax-and 0/imm32
16259     0f 84/jump-if-= $check-mu-index-stmt:error-too-few-inouts/disp32
16260     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
16261     89/<- %ecx 0/r32/eax
16262     # - check index is either a literal or register
16263     # var index-type/edx: (addr type-tree)
16264     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
16265     89/<- %edx 0/r32/eax
16266     # if index type is an atom, it must be a literal or int
16267     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
16268     {
16269       74/jump-if-= break/disp8
16270 $check-mu-index-stmt:index-type-is-atom:
16271       (is-simple-mu-type? %edx 0)  # literal => eax
16272       3d/compare-eax-and 0/imm32/false
16273       75/jump-if-!= $check-mu-index-stmt:index-type-done/disp8
16274       (is-simple-mu-type? %edx 1)  # int => eax
16275       3d/compare-eax-and 0/imm32/false
16276       75/jump-if-!= $check-mu-index-stmt:index-type-done/disp8
16277       (is-simple-mu-type? %edx 7)  # offset => eax
16278       3d/compare-eax-and 0/imm32/false
16279       0f 85/jump-if-!= $check-mu-index-stmt:error-index-offset-atom-type/disp32
16280       e9/jump $check-mu-index-stmt:error-invalid-index-type/disp32
16281     }
16282     # if index type is a non-atom: it must be an offset
16283     {
16284       75/jump-if-!= break/disp8
16285 $check-mu-index-stmt:index-type-is-non-atom:
16286       (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
16287       (is-simple-mu-type? %eax 7)  # offset => eax
16288       3d/compare-eax-and 0/imm32/false
16289       0f 84/jump-if-= $check-mu-index-stmt:error-invalid-index-type/disp32
16290     }
16291 $check-mu-index-stmt:index-type-done:
16292     # check index is either a literal or in a register
16293     {
16294       (is-simple-mu-type? %edx 0)  # literal => eax
16295       3d/compare-eax-and 0/imm32/false
16296       75/jump-if-!= break/disp8
16297 $check-mu-index-stmt:check-index-in-register:
16298       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
16299       0f 84/jump-if-= $check-mu-index-stmt:error-index-on-stack/disp32
16300     }
16301     # - if index is an 'int', check that element type of base has size 1, 2, 4 or 8 bytes.
16302     {
16303       (is-simple-mu-type? %edx 1)  # int => eax
16304       3d/compare-eax-and 0/imm32/false
16305       74/jump-if-= break/disp8
16306 $check-mu-index-stmt:check-index-can-be-int:
16307       (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
16308       (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
16309       (array-element-size %eax)  # => eax
16310       3d/compare-eax-and 1/imm32
16311       74/jump-if-= break/disp8
16312       3d/compare-eax-and 2/imm32
16313       74/jump-if-= break/disp8
16314       3d/compare-eax-and 4/imm32
16315       74/jump-if-= break/disp8
16316       3d/compare-eax-and 8/imm32
16317       74/jump-if-= break/disp8
16318       e9/jump $check-mu-index-stmt:error-index-needs-offset/disp32
16319     }
16320     # - check for too many inouts
16321     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
16322     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
16323     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
16324     3d/compare-eax-and 0/imm32/false
16325     0f 85/jump-if-!= $check-mu-index-stmt:error-too-many-inouts/disp32
16326     # - check for 0 outputs
16327     # var output/edi: (addr var) = stmt->outputs->value
16328     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
16329     3d/compare-eax-and 0/imm32/false
16330     0f 84/jump-if-= $check-mu-index-stmt:error-too-few-outputs/disp32
16331     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
16332     89/<- %edi 0/r32/eax
16333     # - check output type
16334     # must have a non-atomic type
16335     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
16336     89/<- %edx 0/r32/eax
16337     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
16338     0f 85/jump-if-!= $check-mu-index-stmt:error-output-type-not-address/disp32
16339     # type must start with (addr ...)
16340     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
16341     (is-simple-mu-type? %eax 2)  # addr => eax
16342     3d/compare-eax-and 0/imm32/false
16343     0f 84/jump-if-= $check-mu-index-stmt:error-output-type-not-address/disp32
16344     # if tail(base-type) != tail(output-type) abort
16345     (type-tail %ebx)  # => eax
16346     89/<- %ebx 0/r32/eax
16347     (type-tail %edx)  # => eax
16348     (type-equal? %ebx %eax)  # => eax
16349     3d/compare-eax-and 0/imm32/false
16350     0f 84/jump-if-= $check-mu-index-stmt:error-bad-output-type/disp32
16351     # - check for too many outputs
16352     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
16353     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
16354     3d/compare-eax-and 0/imm32/false
16355     0f 85/jump-if-!= $check-mu-index-stmt:error-too-many-outputs/disp32
16356 $check-mu-index-stmt:end:
16357     # . restore registers
16358     5f/pop-to-edi
16359     5e/pop-to-esi
16360     5b/pop-to-ebx
16361     5a/pop-to-edx
16362     59/pop-to-ecx
16363     58/pop-to-eax
16364     # . epilogue
16365     89/<- %esp 5/r32/ebp
16366     5d/pop-to-ebp
16367     c3/return
16368 
16369 $check-mu-index-stmt:error-base-non-array-type:
16370     (write-buffered *(ebp+0x10) "fn ")
16371     8b/-> *(ebp+0xc) 0/r32/eax
16372     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16373     (write-buffered *(ebp+0x10) %eax)
16374     (write-buffered *(ebp+0x10) ": stmt index: var '")
16375     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
16376     (write-buffered *(ebp+0x10) %eax)
16377     (write-buffered *(ebp+0x10) "' is not an array\n")
16378     (flush *(ebp+0x10))
16379     (stop *(ebp+0x14) 1)
16380     # never gets here
16381 
16382 $check-mu-index-stmt:error-base-array-atom-type:
16383     (write-buffered *(ebp+0x10) "fn ")
16384     8b/-> *(ebp+0xc) 0/r32/eax
16385     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16386     (write-buffered *(ebp+0x10) %eax)
16387     (write-buffered *(ebp+0x10) ": stmt index: array '")
16388     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
16389     (write-buffered *(ebp+0x10) %eax)
16390     (write-buffered *(ebp+0x10) "' must specify the type of its elements\n")
16391     (flush *(ebp+0x10))
16392     (stop *(ebp+0x14) 1)
16393     # never gets here
16394 
16395 $check-mu-index-stmt:error-base-address-array-type-on-stack:
16396     (write-buffered *(ebp+0x10) "fn ")
16397     8b/-> *(ebp+0xc) 0/r32/eax
16398     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16399     (write-buffered *(ebp+0x10) %eax)
16400     (write-buffered *(ebp+0x10) ": stmt index: var '")
16401     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
16402     (write-buffered *(ebp+0x10) %eax)
16403     (write-buffered *(ebp+0x10) "' is an addr to an array, and so must live in a register\n")
16404     (flush *(ebp+0x10))
16405     (stop *(ebp+0x14) 1)
16406     # never gets here
16407 
16408 $check-mu-index-stmt:error-base-array-type-in-register:
16409     (write-buffered *(ebp+0x10) "fn ")
16410     8b/-> *(ebp+0xc) 0/r32/eax
16411     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16412     (write-buffered *(ebp+0x10) %eax)
16413     (write-buffered *(ebp+0x10) ": stmt index: var '")
16414     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
16415     (write-buffered *(ebp+0x10) %eax)
16416     (write-buffered *(ebp+0x10) "' is an array, and so must live on the stack\n")
16417     (flush *(ebp+0x10))
16418     (stop *(ebp+0x14) 1)
16419     # never gets here
16420 
16421 $check-mu-index-stmt:error-too-few-inouts:
16422     (write-buffered *(ebp+0x10) "fn ")
16423     8b/-> *(ebp+0xc) 0/r32/eax
16424     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16425     (write-buffered *(ebp+0x10) %eax)
16426     (write-buffered *(ebp+0x10) ": stmt index: too few inouts (2 required)\n")
16427     (flush *(ebp+0x10))
16428     (stop *(ebp+0x14) 1)
16429     # never gets here
16430 
16431 $check-mu-index-stmt:error-invalid-index-type:
16432     (write-buffered *(ebp+0x10) "fn ")
16433     8b/-> *(ebp+0xc) 0/r32/eax
16434     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16435     (write-buffered *(ebp+0x10) %eax)
16436     (write-buffered *(ebp+0x10) ": stmt index: second argument '")
16437     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
16438     (write-buffered *(ebp+0x10) %eax)
16439     (write-buffered *(ebp+0x10) "' must be an int or offset\n")
16440     (flush *(ebp+0x10))
16441     (stop *(ebp+0x14) 1)
16442     # never gets here
16443 
16444 $check-mu-index-stmt:error-index-offset-atom-type:
16445     (write-buffered *(ebp+0x10) "fn ")
16446     8b/-> *(ebp+0xc) 0/r32/eax
16447     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16448     (write-buffered *(ebp+0x10) %eax)
16449     (write-buffered *(ebp+0x10) ": stmt index: offset '")
16450     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
16451     (write-buffered *(ebp+0x10) %eax)
16452     (write-buffered *(ebp+0x10) "' must specify the type of array elements\n")
16453     (flush *(ebp+0x10))
16454     (stop *(ebp+0x14) 1)
16455     # never gets here
16456 
16457 $check-mu-index-stmt:error-index-on-stack:
16458     (write-buffered *(ebp+0x10) "fn ")
16459     8b/-> *(ebp+0xc) 0/r32/eax
16460     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16461     (write-buffered *(ebp+0x10) %eax)
16462     (write-buffered *(ebp+0x10) ": stmt index: second argument '")
16463     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
16464     (write-buffered *(ebp+0x10) %eax)
16465     (write-buffered *(ebp+0x10) "' must be in a register\n")
16466     (flush *(ebp+0x10))
16467     (stop *(ebp+0x14) 1)
16468     # never gets here
16469 
16470 $check-mu-index-stmt:error-index-needs-offset:
16471     (write-buffered *(ebp+0x10) "fn ")
16472     8b/-> *(ebp+0xc) 0/r32/eax
16473     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16474     (write-buffered *(ebp+0x10) %eax)
16475     (write-buffered *(ebp+0x10) ": stmt index: cannot take an int for array '")
16476     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
16477     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
16478     (lookup *eax *(eax+4))  # Var-name Var-name => eax
16479     (write-buffered *(ebp+0x10) %eax)
16480     (write-buffered *(ebp+0x10) "'; create an offset instead. See mu.md for details.\n")
16481     (flush *(ebp+0x10))
16482     (stop *(ebp+0x14) 1)
16483     # never gets here
16484 
16485 $check-mu-index-stmt:error-too-many-inouts:
16486     (write-buffered *(ebp+0x10) "fn ")
16487     8b/-> *(ebp+0xc) 0/r32/eax
16488     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16489     (write-buffered *(ebp+0x10) %eax)
16490     (write-buffered *(ebp+0x10) ": stmt index: too many inouts (2 required)\n")
16491     (flush *(ebp+0x10))
16492     (stop *(ebp+0x14) 1)
16493     # never gets here
16494 
16495 $check-mu-index-stmt:error-too-few-outputs:
16496     (write-buffered *(ebp+0x10) "fn ")
16497     8b/-> *(ebp+0xc) 0/r32/eax
16498     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16499     (write-buffered *(ebp+0x10) %eax)
16500     (write-buffered *(ebp+0x10) ": stmt index: must have an output\n")
16501     (flush *(ebp+0x10))
16502     (stop *(ebp+0x14) 1)
16503     # never gets here
16504 
16505 $check-mu-index-stmt:error-too-many-outputs:
16506     (write-buffered *(ebp+0x10) "fn ")
16507     8b/-> *(ebp+0xc) 0/r32/eax
16508     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16509     (write-buffered *(ebp+0x10) %eax)
16510     (write-buffered *(ebp+0x10) ": stmt index: too many outputs (1 required)\n")
16511     (flush *(ebp+0x10))
16512     (stop *(ebp+0x14) 1)
16513     # never gets here
16514 
16515 $check-mu-index-stmt:error-output-not-in-register:
16516     (write-buffered *(ebp+0x10) "fn ")
16517     8b/-> *(ebp+0xc) 0/r32/eax
16518     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16519     (write-buffered *(ebp+0x10) %eax)
16520     (write-buffered *(ebp+0x10) ": stmt index: output '")
16521     (lookup *edi *(edi+4))  # Var-name Var-name => eax
16522     (write-buffered *(ebp+0x10) %eax)
16523     (write-buffered *(ebp+0x10) "' is not in a register\n")
16524     (flush *(ebp+0x10))
16525     (stop *(ebp+0x14) 1)
16526     # never gets here
16527 
16528 $check-mu-index-stmt:error-output-type-not-address:
16529     (write-buffered *(ebp+0x10) "fn ")
16530     8b/-> *(ebp+0xc) 0/r32/eax
16531     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16532     (write-buffered *(ebp+0x10) %eax)
16533     (write-buffered *(ebp+0x10) ": stmt index: output '")
16534     (lookup *edi *(edi+4))  # Var-name Var-name => eax
16535     (write-buffered *(ebp+0x10) %eax)
16536     (write-buffered *(ebp+0x10) "' must be an addr\n")
16537     (flush *(ebp+0x10))
16538     (stop *(ebp+0x14) 1)
16539     # never gets here
16540 
16541 $check-mu-index-stmt:error-bad-output-type:
16542     (write-buffered *(ebp+0x10) "fn ")
16543     8b/-> *(ebp+0xc) 0/r32/eax
16544     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16545     (write-buffered *(ebp+0x10) %eax)
16546     (write-buffered *(ebp+0x10) ": stmt index: output '")
16547     (lookup *edi *(edi+4))  # Var-name Var-name => eax
16548     (write-buffered *(ebp+0x10) %eax)
16549     (write-buffered *(ebp+0x10) "' does not have the right type\n")
16550     (flush *(ebp+0x10))
16551     (stop *(ebp+0x14) 1)
16552     # never gets here
16553 
16554 check-mu-length-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
16555     # . prologue
16556     55/push-ebp
16557     89/<- %ebp 4/r32/esp
16558     # . save registers
16559     50/push-eax
16560     51/push-ecx
16561     52/push-edx
16562     53/push-ebx
16563     56/push-esi
16564     57/push-edi
16565     # esi = stmt
16566     8b/-> *(ebp+8) 6/r32/esi
16567     # - check for 0 inouts
16568     # var base/ecx: (addr var) = stmt->inouts->value
16569     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
16570 $check-mu-length-stmt:check-no-inouts:
16571     3d/compare-eax-and 0/imm32
16572     0f 84/jump-if-= $check-mu-length-stmt:error-too-few-inouts/disp32
16573     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
16574     89/<- %ecx 0/r32/eax
16575     # - check base type is either (addr array ...) in register or (array ...) on stack
16576     # var base-type/ebx: (addr type-tree) = lookup(base->type)
16577     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
16578     89/<- %ebx 0/r32/eax
16579     # if base-type is an atom, abort with a precise error
16580     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
16581     {
16582       74/jump-if-= break/disp8
16583       (is-simple-mu-type? %ebx 3)  # array => eax
16584       3d/compare-eax-and 0/imm32/false
16585       0f 85/jump-if-!= $check-mu-length-stmt:error-base-array-atom-type/disp32
16586       0f 84/jump-if-= $check-mu-length-stmt:error-base-non-array-type/disp32
16587     }
16588 $check-mu-length-stmt:base-is-compound:
16589     # if type->left not addr or array, abort
16590     {
16591       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
16592       (is-simple-mu-type? %eax 2)  # addr => eax
16593       3d/compare-eax-and 0/imm32/false
16594       75/jump-if-!= break/disp8
16595       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
16596       (is-simple-mu-type? %eax 3)  # array => eax
16597       3d/compare-eax-and 0/imm32/false
16598       75/jump-if-!= break/disp8
16599       e9/jump $check-mu-length-stmt:error-base-non-array-type/disp32
16600     }
16601     # if (type->left == addr) ensure type->right->left == array and type->register exists
16602     {
16603       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
16604       (is-simple-mu-type? %eax 2)  # addr => eax
16605       3d/compare-eax-and 0/imm32/false
16606       74/jump-if-= break/disp8
16607 $check-mu-length-stmt:base-is-addr:
16608       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
16609       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
16610       (is-simple-mu-type? %eax 3)  # array => eax
16611       3d/compare-eax-and 0/imm32/false
16612       0f 84/jump-if-= $check-mu-length-stmt:error-base-non-array-type/disp32
16613 $check-mu-length-stmt:check-base-addr-is-register:
16614       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
16615       0f 84/jump-if-= $check-mu-length-stmt:error-base-address-array-type-on-stack/disp32
16616     }
16617     # if (type->left == array) ensure type->register doesn't exist
16618     {
16619       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
16620       (is-simple-mu-type? %eax 3)  # array => eax
16621       3d/compare-eax-and 0/imm32/false
16622       74/jump-if-= break/disp8
16623 $check-mu-length-stmt:base-is-array:
16624       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
16625       0f 85/jump-if-!= $check-mu-length-stmt:error-base-array-type-in-register/disp32
16626     }
16627     # if (base-type->left == addr) base-type = base-type->right
16628     {
16629       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
16630       (is-simple-mu-type? %eax 2)  # addr => eax
16631       3d/compare-eax-and 0/imm32/false
16632       74/jump-if-= break/disp8
16633       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
16634       89/<- %ebx 0/r32/eax
16635     }
16636     # - check for too many inouts
16637     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
16638     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
16639     3d/compare-eax-and 0/imm32/false
16640     0f 85/jump-if-!= $check-mu-length-stmt:error-too-many-inouts/disp32
16641     # - check for 0 outputs
16642     # var output/edi: (addr var) = stmt->outputs->value
16643     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
16644     3d/compare-eax-and 0/imm32/false
16645     0f 84/jump-if-= $check-mu-length-stmt:error-too-few-outputs/disp32
16646     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
16647     89/<- %edi 0/r32/eax
16648     # - check output type
16649     # must have a non-atomic type
16650     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
16651     (is-simple-mu-type? %eax 1)  # int => eax
16652     3d/compare-eax-and 0/imm32/false
16653     0f 84/jump-if-= $check-mu-length-stmt:error-invalid-output-type/disp32
16654     # - check for too many outputs
16655     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
16656     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
16657     3d/compare-eax-and 0/imm32/false
16658     0f 85/jump-if-!= $check-mu-length-stmt:error-too-many-outputs/disp32
16659 $check-mu-length-stmt:end:
16660     # . restore registers
16661     5f/pop-to-edi
16662     5e/pop-to-esi
16663     5b/pop-to-ebx
16664     5a/pop-to-edx
16665     59/pop-to-ecx
16666     58/pop-to-eax
16667     # . epilogue
16668     89/<- %esp 5/r32/ebp
16669     5d/pop-to-ebp
16670     c3/return
16671 
16672 $check-mu-length-stmt:error-base-non-array-type:
16673     (write-buffered *(ebp+0x10) "fn ")
16674     8b/-> *(ebp+0xc) 0/r32/eax
16675     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16676     (write-buffered *(ebp+0x10) %eax)
16677     (write-buffered *(ebp+0x10) ": stmt length: var '")
16678     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
16679     (write-buffered *(ebp+0x10) %eax)
16680     (write-buffered *(ebp+0x10) "' is not an array\n")
16681     (flush *(ebp+0x10))
16682     (stop *(ebp+0x14) 1)
16683     # never gets here
16684 
16685 $check-mu-length-stmt:error-base-array-atom-type:
16686     (write-buffered *(ebp+0x10) "fn ")
16687     8b/-> *(ebp+0xc) 0/r32/eax
16688     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16689     (write-buffered *(ebp+0x10) %eax)
16690     (write-buffered *(ebp+0x10) ": stmt length: array '")
16691     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
16692     (write-buffered *(ebp+0x10) %eax)
16693     (write-buffered *(ebp+0x10) "' must specify the type of its elements\n")
16694     (flush *(ebp+0x10))
16695     (stop *(ebp+0x14) 1)
16696     # never gets here
16697 
16698 $check-mu-length-stmt:error-base-address-array-type-on-stack:
16699     (write-buffered *(ebp+0x10) "fn ")
16700     8b/-> *(ebp+0xc) 0/r32/eax
16701     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16702     (write-buffered *(ebp+0x10) %eax)
16703     (write-buffered *(ebp+0x10) ": stmt length: var '")
16704     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
16705     (write-buffered *(ebp+0x10) %eax)
16706     (write-buffered *(ebp+0x10) "' is an addr to an array, and so must live in a register\n")
16707     (flush *(ebp+0x10))
16708     (stop *(ebp+0x14) 1)
16709     # never gets here
16710 
16711 $check-mu-length-stmt:error-base-array-type-in-register:
16712     (write-buffered *(ebp+0x10) "fn ")
16713     8b/-> *(ebp+0xc) 0/r32/eax
16714     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16715     (write-buffered *(ebp+0x10) %eax)
16716     (write-buffered *(ebp+0x10) ": stmt length: var '")
16717     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
16718     (write-buffered *(ebp+0x10) %eax)
16719     (write-buffered *(ebp+0x10) "' is an array, and so must live on the stack\n")
16720     (flush *(ebp+0x10))
16721     (stop *(ebp+0x14) 1)
16722     # never gets here
16723 
16724 $check-mu-length-stmt:error-too-few-inouts:
16725     (write-buffered *(ebp+0x10) "fn ")
16726     8b/-> *(ebp+0xc) 0/r32/eax
16727     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16728     (write-buffered *(ebp+0x10) %eax)
16729     (write-buffered *(ebp+0x10) ": stmt length: too few inouts (1 required)\n")
16730     (flush *(ebp+0x10))
16731     (stop *(ebp+0x14) 1)
16732     # never gets here
16733 
16734 $check-mu-length-stmt:error-invalid-index-type:
16735     (write-buffered *(ebp+0x10) "fn ")
16736     8b/-> *(ebp+0xc) 0/r32/eax
16737     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16738     (write-buffered *(ebp+0x10) %eax)
16739     (write-buffered *(ebp+0x10) ": stmt length: second argument '")
16740     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
16741     (write-buffered *(ebp+0x10) %eax)
16742     (write-buffered *(ebp+0x10) "' must be an int or offset\n")
16743     (flush *(ebp+0x10))
16744     (stop *(ebp+0x14) 1)
16745     # never gets here
16746 
16747 $check-mu-length-stmt:error-index-offset-atom-type:
16748     (write-buffered *(ebp+0x10) "fn ")
16749     8b/-> *(ebp+0xc) 0/r32/eax
16750     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16751     (write-buffered *(ebp+0x10) %eax)
16752     (write-buffered *(ebp+0x10) ": stmt length: offset '")
16753     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
16754     (write-buffered *(ebp+0x10) %eax)
16755     (write-buffered *(ebp+0x10) "' must specify the type of array elements\n")
16756     (flush *(ebp+0x10))
16757     (stop *(ebp+0x14) 1)
16758     # never gets here
16759 
16760 $check-mu-length-stmt:error-index-on-stack:
16761     (write-buffered *(ebp+0x10) "fn ")
16762     8b/-> *(ebp+0xc) 0/r32/eax
16763     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16764     (write-buffered *(ebp+0x10) %eax)
16765     (write-buffered *(ebp+0x10) ": stmt length: second argument '")
16766     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
16767     (write-buffered *(ebp+0x10) %eax)
16768     (write-buffered *(ebp+0x10) "' must be in a register\n")
16769     (flush *(ebp+0x10))
16770     (stop *(ebp+0x14) 1)
16771     # never gets here
16772 
16773 $check-mu-length-stmt:error-index-needs-offset:
16774     (write-buffered *(ebp+0x10) "fn ")
16775     8b/-> *(ebp+0xc) 0/r32/eax
16776     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16777     (write-buffered *(ebp+0x10) %eax)
16778     (write-buffered *(ebp+0x10) ": stmt length: cannot take an int for array '")
16779     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
16780     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
16781     (lookup *eax *(eax+4))  # Var-name Var-name => eax
16782     (write-buffered *(ebp+0x10) %eax)
16783     (write-buffered *(ebp+0x10) "'; create an offset instead. See mu.md for details.\n")
16784     (flush *(ebp+0x10))
16785     (stop *(ebp+0x14) 1)
16786     # never gets here
16787 
16788 $check-mu-length-stmt:error-too-many-inouts:
16789     (write-buffered *(ebp+0x10) "fn ")
16790     8b/-> *(ebp+0xc) 0/r32/eax
16791     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16792     (write-buffered *(ebp+0x10) %eax)
16793     (write-buffered *(ebp+0x10) ": stmt length: too many inouts (1 required)\n")
16794     (flush *(ebp+0x10))
16795     (stop *(ebp+0x14) 1)
16796     # never gets here
16797 
16798 $check-mu-length-stmt:error-too-few-outputs:
16799     (write-buffered *(ebp+0x10) "fn ")
16800     8b/-> *(ebp+0xc) 0/r32/eax
16801     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16802     (write-buffered *(ebp+0x10) %eax)
16803     (write-buffered *(ebp+0x10) ": stmt length: must have an output\n")
16804     (flush *(ebp+0x10))
16805     (stop *(ebp+0x14) 1)
16806     # never gets here
16807 
16808 $check-mu-length-stmt:error-too-many-outputs:
16809     (write-buffered *(ebp+0x10) "fn ")
16810     8b/-> *(ebp+0xc) 0/r32/eax
16811     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16812     (write-buffered *(ebp+0x10) %eax)
16813     (write-buffered *(ebp+0x10) ": stmt length: too many outputs (1 required)\n")
16814     (flush *(ebp+0x10))
16815     (stop *(ebp+0x14) 1)
16816     # never gets here
16817 
16818 $check-mu-length-stmt:error-output-not-in-register:
16819     (write-buffered *(ebp+0x10) "fn ")
16820     8b/-> *(ebp+0xc) 0/r32/eax
16821     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16822     (write-buffered *(ebp+0x10) %eax)
16823     (write-buffered *(ebp+0x10) ": stmt length: output '")
16824     (lookup *edi *(edi+4))  # Var-name Var-name => eax
16825     (write-buffered *(ebp+0x10) %eax)
16826     (write-buffered *(ebp+0x10) "' is not in a register\n")
16827     (flush *(ebp+0x10))
16828     (stop *(ebp+0x14) 1)
16829     # never gets here
16830 
16831 $check-mu-length-stmt:error-invalid-output-type:
16832     (write-buffered *(ebp+0x10) "fn ")
16833     8b/-> *(ebp+0xc) 0/r32/eax
16834     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16835     (write-buffered *(ebp+0x10) %eax)
16836     (write-buffered *(ebp+0x10) ": stmt length: output '")
16837     (lookup *edi *(edi+4))  # Var-name Var-name => eax
16838     (write-buffered *(ebp+0x10) %eax)
16839     (write-buffered *(ebp+0x10) "' does not have the right type\n")
16840     (flush *(ebp+0x10))
16841     (stop *(ebp+0x14) 1)
16842     # never gets here
16843 
16844 check-mu-compute-offset-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
16845     # . prologue
16846     55/push-ebp
16847     89/<- %ebp 4/r32/esp
16848     # . save registers
16849     50/push-eax
16850     51/push-ecx
16851     52/push-edx
16852     53/push-ebx
16853     56/push-esi
16854     57/push-edi
16855     # esi = stmt
16856     8b/-> *(ebp+8) 6/r32/esi
16857     # - check for 0 inouts
16858     # var base/ecx: (addr var) = stmt->inouts->value
16859     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
16860 $check-mu-compute-offset-stmt:check-no-inouts:
16861     3d/compare-eax-and 0/imm32
16862     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-too-few-inouts/disp32
16863     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
16864     89/<- %ecx 0/r32/eax
16865     # - check base type is either (addr array ...) in register or (array ...) on stack
16866     # var base-type/ebx: (addr type-tree) = lookup(base->type)
16867     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
16868     89/<- %ebx 0/r32/eax
16869     # if base-type is an atom, abort with a precise error
16870     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
16871     {
16872       74/jump-if-= break/disp8
16873       (is-simple-mu-type? %ebx 3)  # array => eax
16874       3d/compare-eax-and 0/imm32/false
16875       0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-base-array-atom-type/disp32
16876       0f 84/jump-if-= $check-mu-compute-offset-stmt:error-base-non-array-type/disp32
16877     }
16878 $check-mu-compute-offset-stmt:base-is-compound:
16879     # if type->left not addr or array, abort
16880     {
16881       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
16882       (is-simple-mu-type? %eax 2)  # addr => eax
16883       3d/compare-eax-and 0/imm32/false
16884       75/jump-if-!= break/disp8
16885       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
16886       (is-simple-mu-type? %eax 3)  # array => eax
16887       3d/compare-eax-and 0/imm32/false
16888       75/jump-if-!= break/disp8
16889       e9/jump $check-mu-compute-offset-stmt:error-base-non-array-type/disp32
16890     }
16891     # if (type->left == addr) ensure type->right->left == array and type->register exists
16892     {
16893       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
16894       (is-simple-mu-type? %eax 2)  # addr => eax
16895       3d/compare-eax-and 0/imm32/false
16896       74/jump-if-= break/disp8
16897 $check-mu-compute-offset-stmt:base-is-addr:
16898       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
16899       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
16900       (is-simple-mu-type? %eax 3)  # array => eax
16901       3d/compare-eax-and 0/imm32/false
16902       0f 84/jump-if-= $check-mu-compute-offset-stmt:error-base-non-array-type/disp32
16903     }
16904     # if (base-type->left == addr) base-type = base-type->right
16905     {
16906       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
16907       (is-simple-mu-type? %eax 2)  # addr => eax
16908       3d/compare-eax-and 0/imm32/false
16909       74/jump-if-= break/disp8
16910       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
16911       89/<- %ebx 0/r32/eax
16912     }
16913     # - check for 1 inout
16914     # var index/ecx: (addr stmt-var) = stmt->inouts->next->value
16915     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
16916     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
16917 $check-mu-compute-offset-stmt:check-single-inout:
16918     3d/compare-eax-and 0/imm32
16919     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-too-few-inouts/disp32
16920     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
16921     89/<- %ecx 0/r32/eax
16922     # - check index is either a literal or register
16923     # var index-type/edx: (addr type-tree)
16924     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
16925     89/<- %edx 0/r32/eax
16926     # index type must be a literal or int
16927     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
16928     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-invalid-index-type/disp32
16929     {
16930 $check-mu-compute-offset-stmt:index-type-is-atom:
16931       (is-simple-mu-type? %edx 0)  # literal => eax
16932       3d/compare-eax-and 0/imm32/false
16933       75/jump-if-!= break/disp8
16934       (is-simple-mu-type? %edx 1)  # int => eax
16935       3d/compare-eax-and 0/imm32/false
16936       75/jump-if-!= break/disp8
16937       e9/jump $check-mu-compute-offset-stmt:error-invalid-index-type/disp32
16938     }
16939     # - check for too many inouts
16940     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
16941     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
16942     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
16943     3d/compare-eax-and 0/imm32/false
16944     0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-too-many-inouts/disp32
16945     # - check for 0 outputs
16946     # var output/edi: (addr var) = stmt->outputs->value
16947     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
16948     3d/compare-eax-and 0/imm32/false
16949     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-too-few-outputs/disp32
16950     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
16951     89/<- %edi 0/r32/eax
16952     # - check output type
16953     # must have a non-atomic type
16954     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
16955     89/<- %edx 0/r32/eax
16956     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
16957     0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-output-type-not-offset/disp32
16958     # type must start with (offset ...)
16959     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
16960     (is-simple-mu-type? %eax 7)  # offset => eax
16961     3d/compare-eax-and 0/imm32/false
16962     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-output-type-not-offset/disp32
16963     # if tail(base-type) != tail(output-type) abort
16964     (type-tail %ebx)  # => eax
16965     89/<- %ebx 0/r32/eax
16966     (type-tail %edx)  # => eax
16967     (type-equal? %ebx %eax)  # => eax
16968     3d/compare-eax-and 0/imm32/false
16969     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-bad-output-type/disp32
16970     # - check for too many outputs
16971     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
16972     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
16973     3d/compare-eax-and 0/imm32/false
16974     0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-too-many-outputs/disp32
16975 $check-mu-compute-offset-stmt:end:
16976     # . restore registers
16977     5f/pop-to-edi
16978     5e/pop-to-esi
16979     5b/pop-to-ebx
16980     5a/pop-to-edx
16981     59/pop-to-ecx
16982     58/pop-to-eax
16983     # . epilogue
16984     89/<- %esp 5/r32/ebp
16985     5d/pop-to-ebp
16986     c3/return
16987 
16988 $check-mu-compute-offset-stmt:error-base-non-array-type:
16989     (write-buffered *(ebp+0x10) "fn ")
16990     8b/-> *(ebp+0xc) 0/r32/eax
16991     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16992     (write-buffered *(ebp+0x10) %eax)
16993     (write-buffered *(ebp+0x10) ": stmt compute-offset: var '")
16994     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
16995     (write-buffered *(ebp+0x10) %eax)
16996     (write-buffered *(ebp+0x10) "' is not an array\n")
16997     (flush *(ebp+0x10))
16998     (stop *(ebp+0x14) 1)
16999     # never gets here
17000 
17001 $check-mu-compute-offset-stmt:error-base-array-atom-type:
17002     (write-buffered *(ebp+0x10) "fn ")
17003     8b/-> *(ebp+0xc) 0/r32/eax
17004     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17005     (write-buffered *(ebp+0x10) %eax)
17006     (write-buffered *(ebp+0x10) ": stmt compute-offset: array '")
17007     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
17008     (write-buffered *(ebp+0x10) %eax)
17009     (write-buffered *(ebp+0x10) "' must specify the type of its elements\n")
17010     (flush *(ebp+0x10))
17011     (stop *(ebp+0x14) 1)
17012     # never gets here
17013 
17014 $check-mu-compute-offset-stmt:error-too-few-inouts:
17015     (write-buffered *(ebp+0x10) "fn ")
17016     8b/-> *(ebp+0xc) 0/r32/eax
17017     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17018     (write-buffered *(ebp+0x10) %eax)
17019     (write-buffered *(ebp+0x10) ": stmt compute-offset: too few inouts (2 required)\n")
17020     (flush *(ebp+0x10))
17021     (stop *(ebp+0x14) 1)
17022     # never gets here
17023 
17024 $check-mu-compute-offset-stmt:error-invalid-index-type:
17025     (write-buffered *(ebp+0x10) "fn ")
17026     8b/-> *(ebp+0xc) 0/r32/eax
17027     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17028     (write-buffered *(ebp+0x10) %eax)
17029     (write-buffered *(ebp+0x10) ": stmt compute-offset: second argument '")
17030     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
17031     (write-buffered *(ebp+0x10) %eax)
17032     (write-buffered *(ebp+0x10) "' must be an int\n")
17033     (flush *(ebp+0x10))
17034     (stop *(ebp+0x14) 1)
17035     # never gets here
17036 
17037 $check-mu-compute-offset-stmt:error-index-offset-atom-type:
17038     (write-buffered *(ebp+0x10) "fn ")
17039     8b/-> *(ebp+0xc) 0/r32/eax
17040     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17041     (write-buffered *(ebp+0x10) %eax)
17042     (write-buffered *(ebp+0x10) ": stmt compute-offset: offset '")
17043     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
17044     (write-buffered *(ebp+0x10) %eax)
17045     (write-buffered *(ebp+0x10) "' must specify the type of array elements\n")
17046     (flush *(ebp+0x10))
17047     (stop *(ebp+0x14) 1)
17048     # never gets here
17049 
17050 $check-mu-compute-offset-stmt:error-index-on-stack:
17051     (write-buffered *(ebp+0x10) "fn ")
17052     8b/-> *(ebp+0xc) 0/r32/eax
17053     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17054     (write-buffered *(ebp+0x10) %eax)
17055     (write-buffered *(ebp+0x10) ": stmt compute-offset: second argument '")
17056     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
17057     (write-buffered *(ebp+0x10) %eax)
17058     (write-buffered *(ebp+0x10) "' must be in a register\n")
17059     (flush *(ebp+0x10))
17060     (stop *(ebp+0x14) 1)
17061     # never gets here
17062 
17063 $check-mu-compute-offset-stmt:error-too-many-inouts:
17064     (write-buffered *(ebp+0x10) "fn ")
17065     8b/-> *(ebp+0xc) 0/r32/eax
17066     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17067     (write-buffered *(ebp+0x10) %eax)
17068     (write-buffered *(ebp+0x10) ": stmt compute-offset: too many inouts (2 required)\n")
17069     (flush *(ebp+0x10))
17070     (stop *(ebp+0x14) 1)
17071     # never gets here
17072 
17073 $check-mu-compute-offset-stmt:error-too-few-outputs:
17074     (write-buffered *(ebp+0x10) "fn ")
17075     8b/-> *(ebp+0xc) 0/r32/eax
17076     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17077     (write-buffered *(ebp+0x10) %eax)
17078     (write-buffered *(ebp+0x10) ": stmt compute-offset: must have an output\n")
17079     (flush *(ebp+0x10))
17080     (stop *(ebp+0x14) 1)
17081     # never gets here
17082 
17083 $check-mu-compute-offset-stmt:error-too-many-outputs:
17084     (write-buffered *(ebp+0x10) "fn ")
17085     8b/-> *(ebp+0xc) 0/r32/eax
17086     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17087     (write-buffered *(ebp+0x10) %eax)
17088     (write-buffered *(ebp+0x10) ": stmt compute-offset: too many outputs (1 required)\n")
17089     (flush *(ebp+0x10))
17090     (stop *(ebp+0x14) 1)
17091     # never gets here
17092 
17093 $check-mu-compute-offset-stmt:error-output-not-in-register:
17094     (write-buffered *(ebp+0x10) "fn ")
17095     8b/-> *(ebp+0xc) 0/r32/eax
17096     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17097     (write-buffered *(ebp+0x10) %eax)
17098     (write-buffered *(ebp+0x10) ": stmt compute-offset: output '")
17099     (lookup *edi *(edi+4))  # Var-name Var-name => eax
17100     (write-buffered *(ebp+0x10) %eax)
17101     (write-buffered *(ebp+0x10) "' is not in a register\n")
17102     (flush *(ebp+0x10))
17103     (stop *(ebp+0x14) 1)
17104     # never gets here
17105 
17106 $check-mu-compute-offset-stmt:error-output-type-not-offset:
17107     (write-buffered *(ebp+0x10) "fn ")
17108     8b/-> *(ebp+0xc) 0/r32/eax
17109     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17110     (write-buffered *(ebp+0x10) %eax)
17111     (write-buffered *(ebp+0x10) ": stmt compute-offset: output '")
17112     (lookup *edi *(edi+4))  # Var-name Var-name => eax
17113     (write-buffered *(ebp+0x10) %eax)
17114     (write-buffered *(ebp+0x10) "' must be an offset\n")
17115     (flush *(ebp+0x10))
17116     (stop *(ebp+0x14) 1)
17117     # never gets here
17118 
17119 $check-mu-compute-offset-stmt:error-bad-output-type:
17120     (write-buffered *(ebp+0x10) "fn ")
17121     8b/-> *(ebp+0xc) 0/r32/eax
17122     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17123     (write-buffered *(ebp+0x10) %eax)
17124     (write-buffered *(ebp+0x10) ": stmt compute-offset: output '")
17125     (lookup *edi *(edi+4))  # Var-name Var-name => eax
17126     (write-buffered *(ebp+0x10) %eax)
17127     (write-buffered *(ebp+0x10) "' does not have the right type\n")
17128     (flush *(ebp+0x10))
17129     (stop *(ebp+0x14) 1)
17130     # never gets here
17131 
17132 check-mu-copy-object-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
17133     # . prologue
17134     55/push-ebp
17135     89/<- %ebp 4/r32/esp
17136     # . save registers
17137 $check-mu-copy-object-stmt:end:
17138     # . restore registers
17139     # . epilogue
17140     89/<- %esp 5/r32/ebp
17141     5d/pop-to-ebp
17142     c3/return
17143 
17144 check-mu-allocate-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
17145     # . prologue
17146     55/push-ebp
17147     89/<- %ebp 4/r32/esp
17148     # . save registers
17149 $check-mu-allocate-stmt:end:
17150     # . restore registers
17151     # . epilogue
17152     89/<- %esp 5/r32/ebp
17153     5d/pop-to-ebp
17154     c3/return
17155 
17156 check-mu-populate-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
17157     # . prologue
17158     55/push-ebp
17159     89/<- %ebp 4/r32/esp
17160     # . save registers
17161 $check-mu-populate-stmt:end:
17162     # . restore registers
17163     # . epilogue
17164     89/<- %esp 5/r32/ebp
17165     5d/pop-to-ebp
17166     c3/return
17167 
17168 check-mu-populate-stream-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
17169     # . prologue
17170     55/push-ebp
17171     89/<- %ebp 4/r32/esp
17172     # . save registers
17173 $check-mu-populate-stream-stmt:end:
17174     # . restore registers
17175     # . epilogue
17176     89/<- %esp 5/r32/ebp
17177     5d/pop-to-ebp
17178     c3/return
17179 
17180 check-mu-read-from-stream-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
17181     # . prologue
17182     55/push-ebp
17183     89/<- %ebp 4/r32/esp
17184     # . save registers
17185     50/push-eax
17186     51/push-ecx
17187     52/push-edx
17188     53/push-ebx
17189     56/push-esi
17190     57/push-edi
17191     # esi = stmt
17192     8b/-> *(ebp+8) 6/r32/esi
17193     # - check for 0 inouts
17194     # var base/ecx: (addr var) = stmt->inouts->value
17195     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
17196 $check-mu-read-from-stream-stmt:check-no-inouts:
17197     3d/compare-eax-and 0/imm32
17198     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-too-few-inouts/disp32
17199     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
17200     89/<- %ecx 0/r32/eax
17201     # - check base type is (addr stream T)
17202     # var base-type/ebx: (addr type-tree) = lookup(base->type)
17203     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
17204     89/<- %ebx 0/r32/eax
17205 $check-mu-read-from-stream-stmt:check-base-is-compound:
17206     # if base-type is an atom, abort
17207     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
17208     0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-invalid-base-type/disp32
17209 $check-mu-read-from-stream-stmt:check-base-is-addr:
17210     # if type->left not addr, abort
17211     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
17212     (is-simple-mu-type? %eax 2)  # addr => eax
17213     3d/compare-eax-and 0/imm32/false
17214     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-invalid-base-type/disp32
17215 $check-mu-read-from-stream-stmt:check-base-is-addr-to-stream:
17216     # base-type = base-type->right
17217     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
17218     89/<- %ebx 0/r32/eax
17219     # ensure base-type->left == stream
17220     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
17221     (is-simple-mu-type? %eax 0xb)  # stream => eax
17222     3d/compare-eax-and 0/imm32/false
17223     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-invalid-base-type/disp32
17224     # - check target type is (addr T)
17225     # var target/ecx: (addr stmt-var) = stmt->inouts->next->value
17226     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
17227     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
17228 $check-mu-read-from-stream-stmt:check-single-inout:
17229     3d/compare-eax-and 0/imm32
17230     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-too-few-inouts/disp32
17231     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
17232     89/<- %ecx 0/r32/eax
17233     # var target-type/edx: (addr type-tree)
17234     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
17235     89/<- %edx 0/r32/eax
17236     # if target-type is an atom, it must be a literal or int
17237 $check-mu-read-from-stream-stmt:check-target-is-compound:
17238     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
17239     0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-target-type-not-address/disp32
17240 $check-mu-read-from-stream-stmt:check-target-type:
17241     # target type must start with (addr ...)
17242     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
17243     (is-simple-mu-type? %eax 2)  # addr => eax
17244     3d/compare-eax-and 0/imm32/false
17245     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-target-type-not-address/disp32
17246     # if tail(base-type) != tail(target-type) abort
17247     (type-tail %ebx)  # => eax
17248     89/<- %ebx 0/r32/eax
17249     (type-tail %edx)  # => eax
17250     (type-equal? %ebx %eax)  # => eax
17251     3d/compare-eax-and 0/imm32/false
17252     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-invalid-target-type/disp32
17253 $check-mu-read-from-stream-stmt:check-too-many-inouts:
17254     # - check for too many inouts
17255     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
17256     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
17257     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
17258     3d/compare-eax-and 0/imm32/false
17259     0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-too-many-inouts/disp32
17260 $check-mu-read-from-stream-stmt:check-unexpected-output:
17261     # - check for any output
17262     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
17263     3d/compare-eax-and 0/imm32/false
17264     0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-unexpected-output/disp32
17265 $check-mu-read-from-stream-stmt:end:
17266     # . restore registers
17267     5f/pop-to-edi
17268     5e/pop-to-esi
17269     5b/pop-to-ebx
17270     5a/pop-to-edx
17271     59/pop-to-ecx
17272     58/pop-to-eax
17273     # . epilogue
17274     89/<- %esp 5/r32/ebp
17275     5d/pop-to-ebp
17276     c3/return
17277 
17278 $check-mu-read-from-stream-stmt:error-invalid-base-type:
17279     (write-buffered *(ebp+0x10) "fn ")
17280     8b/-> *(ebp+0xc) 0/r32/eax
17281     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17282     (write-buffered *(ebp+0x10) %eax)
17283     (write-buffered *(ebp+0x10) ": stmt read-from-stream: var '")
17284     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
17285     (write-buffered *(ebp+0x10) %eax)
17286     (write-buffered *(ebp+0x10) "' must be an addr to a stream\n")
17287     (flush *(ebp+0x10))
17288     (stop *(ebp+0x14) 1)
17289     # never gets here
17290 
17291 $check-mu-read-from-stream-stmt:error-too-few-inouts:
17292     (write-buffered *(ebp+0x10) "fn ")
17293     8b/-> *(ebp+0xc) 0/r32/eax
17294     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17295     (write-buffered *(ebp+0x10) %eax)
17296     (write-buffered *(ebp+0x10) ": stmt read-from-stream: too few inouts (2 required)\n")
17297     (flush *(ebp+0x10))
17298     (stop *(ebp+0x14) 1)
17299     # never gets here
17300 
17301 $check-mu-read-from-stream-stmt:error-target-type-not-address:
17302     (write-buffered *(ebp+0x10) "fn ")
17303     8b/-> *(ebp+0xc) 0/r32/eax
17304     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17305     (write-buffered *(ebp+0x10) %eax)
17306     (write-buffered *(ebp+0x10) ": stmt read-from-stream: target '")
17307     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
17308     (write-buffered *(ebp+0x10) %eax)
17309     (write-buffered *(ebp+0x10) "' must be an addr\n")
17310     (flush *(ebp+0x10))
17311     (stop *(ebp+0x14) 1)
17312     # never gets here
17313 
17314 $check-mu-read-from-stream-stmt:error-invalid-target-type:
17315     (write-buffered *(ebp+0x10) "fn ")
17316     8b/-> *(ebp+0xc) 0/r32/eax
17317     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17318     (write-buffered *(ebp+0x10) %eax)
17319     (write-buffered *(ebp+0x10) ": stmt read-from-stream: second inout '")
17320     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
17321     (write-buffered *(ebp+0x10) %eax)
17322     (write-buffered *(ebp+0x10) "' does not have the right type\n")
17323     (flush *(ebp+0x10))
17324     (stop *(ebp+0x14) 1)
17325     # never gets here
17326 
17327 $check-mu-read-from-stream-stmt:error-too-many-inouts:
17328     (write-buffered *(ebp+0x10) "fn ")
17329     8b/-> *(ebp+0xc) 0/r32/eax
17330     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17331     (write-buffered *(ebp+0x10) %eax)
17332     (write-buffered *(ebp+0x10) ": stmt read-from-stream: too many inouts (2 required)\n")
17333     (flush *(ebp+0x10))
17334     (stop *(ebp+0x14) 1)
17335     # never gets here
17336 
17337 $check-mu-read-from-stream-stmt:error-unexpected-output:
17338     (write-buffered *(ebp+0x10) "fn ")
17339     8b/-> *(ebp+0xc) 0/r32/eax
17340     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17341     (write-buffered *(ebp+0x10) %eax)
17342     (write-buffered *(ebp+0x10) ": stmt read-from-stream: unexpected output\n")
17343     (flush *(ebp+0x10))
17344     (stop *(ebp+0x14) 1)
17345     # never gets here
17346 
17347 check-mu-write-to-stream-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
17348     # . prologue
17349     55/push-ebp
17350     89/<- %ebp 4/r32/esp
17351     # . save registers
17352     50/push-eax
17353     51/push-ecx
17354     52/push-edx
17355     53/push-ebx
17356     56/push-esi
17357     57/push-edi
17358     # esi = stmt
17359     8b/-> *(ebp+8) 6/r32/esi
17360     # - check for 0 inouts
17361     # var base/ecx: (addr var) = stmt->inouts->value
17362     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
17363 $check-mu-write-to-stream-stmt:check-no-inouts:
17364     3d/compare-eax-and 0/imm32
17365     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-too-few-inouts/disp32
17366     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
17367     89/<- %ecx 0/r32/eax
17368     # - check base type is (addr stream T)
17369     # var base-type/ebx: (addr type-tree) = lookup(base->type)
17370     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
17371     89/<- %ebx 0/r32/eax
17372 $check-mu-write-to-stream-stmt:check-base-is-compound:
17373     # if base-type is an atom, abort
17374     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
17375     0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-invalid-base-type/disp32
17376 $check-mu-write-to-stream-stmt:check-base-is-addr:
17377     # if type->left not addr, abort
17378     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
17379     (is-simple-mu-type? %eax 2)  # addr => eax
17380     3d/compare-eax-and 0/imm32/false
17381     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-invalid-base-type/disp32
17382 $check-mu-write-to-stream-stmt:check-base-is-addr-to-stream:
17383     # base-type = base-type->right
17384     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
17385     89/<- %ebx 0/r32/eax
17386     # ensure base-type->left == stream
17387     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
17388     (is-simple-mu-type? %eax 0xb)  # stream => eax
17389     3d/compare-eax-and 0/imm32/false
17390     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-invalid-base-type/disp32
17391     # - check target type is (addr T)
17392     # var target/ecx: (addr stmt-var) = stmt->inouts->next->value
17393     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
17394     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
17395 $check-mu-write-to-stream-stmt:check-single-inout:
17396     3d/compare-eax-and 0/imm32
17397     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-too-few-inouts/disp32
17398     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
17399     89/<- %ecx 0/r32/eax
17400     # var target-type/edx: (addr type-tree)
17401     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
17402     89/<- %edx 0/r32/eax
17403     # if target-type is an atom, it must be a literal or int
17404 $check-mu-write-to-stream-stmt:check-target-is-compound:
17405     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
17406     0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-target-type-not-address/disp32
17407 $check-mu-write-to-stream-stmt:check-target-type:
17408     # target type must start with (addr ...)
17409     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
17410     (is-simple-mu-type? %eax 2)  # addr => eax
17411     3d/compare-eax-and 0/imm32/false
17412     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-target-type-not-address/disp32
17413     # if tail(base-type) != tail(target-type) abort
17414     (type-tail %ebx)  # => eax
17415     89/<- %ebx 0/r32/eax
17416     (type-tail %edx)  # => eax
17417     (type-equal? %ebx %eax)  # => eax
17418     3d/compare-eax-and 0/imm32/false
17419     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-invalid-target-type/disp32
17420 $check-mu-write-to-stream-stmt:check-too-many-inouts:
17421     # - check for too many inouts
17422     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
17423     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
17424     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
17425     3d/compare-eax-and 0/imm32/false
17426     0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-too-many-inouts/disp32
17427 $check-mu-write-to-stream-stmt:check-unexpected-output:
17428     # - check for any output
17429     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
17430     3d/compare-eax-and 0/imm32/false
17431     0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-unexpected-output/disp32
17432 $check-mu-write-to-stream-stmt:end:
17433     # . restore registers
17434     5f/pop-to-edi
17435     5e/pop-to-esi
17436     5b/pop-to-ebx
17437     5a/pop-to-edx
17438     59/pop-to-ecx
17439     58/pop-to-eax
17440     # . epilogue
17441     89/<- %esp 5/r32/ebp
17442     5d/pop-to-ebp
17443     c3/return
17444 
17445 $check-mu-write-to-stream-stmt:error-invalid-base-type:
17446     (write-buffered *(ebp+0x10) "fn ")
17447     8b/-> *(ebp+0xc) 0/r32/eax
17448     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17449     (write-buffered *(ebp+0x10) %eax)
17450     (write-buffered *(ebp+0x10) ": stmt write-to-stream: var '")
17451     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
17452     (write-buffered *(ebp+0x10) %eax)
17453     (write-buffered *(ebp+0x10) "' must be an addr to a stream\n")
17454     (flush *(ebp+0x10))
17455     (stop *(ebp+0x14) 1)
17456     # never gets here
17457 
17458 $check-mu-write-to-stream-stmt:error-too-few-inouts:
17459     (write-buffered *(ebp+0x10) "fn ")
17460     8b/-> *(ebp+0xc) 0/r32/eax
17461     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17462     (write-buffered *(ebp+0x10) %eax)
17463     (write-buffered *(ebp+0x10) ": stmt write-to-stream: too few inouts (2 required)\n")
17464     (flush *(ebp+0x10))
17465     (stop *(ebp+0x14) 1)
17466     # never gets here
17467 
17468 $check-mu-write-to-stream-stmt:error-target-type-not-address:
17469     (write-buffered *(ebp+0x10) "fn ")
17470     8b/-> *(ebp+0xc) 0/r32/eax
17471     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17472     (write-buffered *(ebp+0x10) %eax)
17473     (write-buffered *(ebp+0x10) ": stmt write-to-stream: target '")
17474     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
17475     (write-buffered *(ebp+0x10) %eax)
17476     (write-buffered *(ebp+0x10) "' must be an addr\n")
17477     (flush *(ebp+0x10))
17478     (stop *(ebp+0x14) 1)
17479     # never gets here
17480 
17481 $check-mu-write-to-stream-stmt:error-invalid-target-type:
17482     (write-buffered *(ebp+0x10) "fn ")
17483     8b/-> *(ebp+0xc) 0/r32/eax
17484     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17485     (write-buffered *(ebp+0x10) %eax)
17486     (write-buffered *(ebp+0x10) ": stmt write-to-stream: second inout '")
17487     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
17488     (write-buffered *(ebp+0x10) %eax)
17489     (write-buffered *(ebp+0x10) "' does not have the right type\n")
17490     (flush *(ebp+0x10))
17491     (stop *(ebp+0x14) 1)
17492     # never gets here
17493 
17494 $check-mu-write-to-stream-stmt:error-too-many-inouts:
17495     (write-buffered *(ebp+0x10) "fn ")
17496     8b/-> *(ebp+0xc) 0/r32/eax
17497     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17498     (write-buffered *(ebp+0x10) %eax)
17499     (write-buffered *(ebp+0x10) ": stmt write-to-stream: too many inouts (2 required)\n")
17500     (flush *(ebp+0x10))
17501     (stop *(ebp+0x14) 1)
17502     # never gets here
17503 
17504 $check-mu-write-to-stream-stmt:error-unexpected-output:
17505     (write-buffered *(ebp+0x10) "fn ")
17506     8b/-> *(ebp+0xc) 0/r32/eax
17507     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17508     (write-buffered *(ebp+0x10) %eax)
17509     (write-buffered *(ebp+0x10) ": stmt write-to-stream: unexpected output\n")
17510     (flush *(ebp+0x10))
17511     (stop *(ebp+0x14) 1)
17512     # never gets here
17513 
17514 check-mu-convert-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
17515     # . prologue
17516     55/push-ebp
17517     89/<- %ebp 4/r32/esp
17518     # . save registers
17519 $check-mu-convert-stmt:end:
17520     # . restore registers
17521     # . epilogue
17522     89/<- %esp 5/r32/ebp
17523     5d/pop-to-ebp
17524     c3/return
17525 
17526 check-mu-call:  # stmt: (addr stmt), callee: (addr function), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
17527     # . prologue
17528     55/push-ebp
17529     89/<- %ebp 4/r32/esp
17530     # var type-parameters: (addr table (handle array byte) (addr type-tree) 8)
17531     68/push 0/imm32
17532     # var type-parameters-storage: (table (handle array byte) (addr type-tree) 8)
17533     81 5/subop/subtract %esp 0x60/imm32
17534     68/push 0x60/imm32/size
17535     68/push 0/imm32/read
17536     68/push 0/imm32/write
17537     # save a pointer to type-parameters-storage at type-parameters
17538     89/<- *(ebp-4) 4/r32/esp
17539     (clear-stream *(ebp-4))
17540     # . save registers
17541     50/push-eax
17542     51/push-ecx
17543     52/push-edx
17544     53/push-ebx
17545     56/push-esi
17546     57/push-edi
17547     # esi = stmt
17548     8b/-> *(ebp+8) 6/r32/esi
17549     # edi = callee
17550     8b/-> *(ebp+0xc) 7/r32/edi
17551     # var inouts/ecx: (addr stmt-var) = lookup(stmt->inouts)
17552     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
17553     89/<- %ecx 0/r32/eax
17554     # var expected/edx: (addr list var) = lookup(f->inouts)
17555     (lookup *(edi+8) *(edi+0xc))  # Function-inouts Function-inouts => eax
17556     89/<- %edx 0/r32/eax
17557     {
17558 $check-mu-call:check-for-inouts:
17559       # if (inouts == 0) break
17560       81 7/subop/compare %ecx 0/imm32
17561       0f 84/jump-if-= break/disp32
17562       # if (expected == 0) error
17563       81 7/subop/compare %edx 0/imm32
17564       0f 84/jump-if-= break/disp32
17565 $check-mu-call:check-inout-type:
17566       # var v/eax: (addr v) = lookup(inouts->value)
17567       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
17568       # var t/ebx: (addr type-tree) = lookup(v->type)
17569       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
17570       89/<- %ebx 0/r32/eax
17571       # if (inouts->is-deref?) t = t->right  # TODO: check that t->left is an addr
17572       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
17573       {
17574         74/jump-if-= break/disp8
17575         (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
17576         89/<- %ebx 0/r32/eax
17577         # if t->right is null, t = t->left
17578         81 7/subop/compare *(ebx+0xc) 0/imm32  # Type-tree-right
17579         75/jump-if-!= break/disp8
17580         (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
17581         89/<- %ebx 0/r32/eax
17582       }
17583       # var v2/eax: (addr v) = lookup(expected->value)
17584       (lookup *edx *(edx+4))  # List-value List-value => eax
17585       # var t2/eax: (addr type-tree) = lookup(v2->type)
17586       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
17587       # if (t != t2) error
17588       (type-match? %eax %ebx *(ebp-4))  # => eax
17589       3d/compare-eax-and 0/imm32/false
17590       {
17591         0f 85/jump-if-!= break/disp32
17592         (write-buffered *(ebp+0x14) "fn ")
17593         8b/-> *(ebp+0x10) 0/r32/eax
17594         (lookup *eax *(eax+4))  # Function-name Function-name => eax
17595         (write-buffered *(ebp+0x14) %eax)
17596         (write-buffered *(ebp+0x14) ": call ")
17597         (lookup *edi *(edi+4))  # Function-name Function-name => eax
17598         (write-buffered *(ebp+0x14) %eax)
17599         (write-buffered *(ebp+0x14) ": type for inout '")
17600         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
17601         (lookup *eax *(eax+4))  # Var-name Var-name => eax
17602         (write-buffered *(ebp+0x14) %eax)
17603         (write-buffered *(ebp+0x14) "' is not right\n")
17604         (flush *(ebp+0x14))
17605         (stop *(ebp+0x18) 1)
17606       }
17607 $check-mu-call:continue-to-next-inout:
17608       # inouts = lookup(inouts->next)
17609       (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
17610       89/<- %ecx 0/r32/eax
17611       # expected = lookup(expected->next)
17612       (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
17613       89/<- %edx 0/r32/eax
17614       #
17615       e9/jump loop/disp32
17616     }
17617 $check-mu-call:check-inout-count:
17618     # if (inouts == expected) proceed
17619     39/compare %ecx 2/r32/edx
17620     {
17621       0f 84/jump-if-= break/disp32
17622       # exactly one of the two is null
17623       # if (inouts == 0) error("too many inouts")
17624       {
17625         81 7/subop/compare %ecx 0/imm32
17626         0f 84/jump-if-= break/disp32
17627         (write-buffered *(ebp+0x14) "fn ")
17628         8b/-> *(ebp+0x10) 0/r32/eax
17629         (lookup *eax *(eax+4))  # Function-name Function-name => eax
17630         (write-buffered *(ebp+0x14) %eax)
17631         (write-buffered *(ebp+0x14) ": call ")
17632         (lookup *edi *(edi+4))  # Function-name Function-name => eax
17633         (write-buffered *(ebp+0x14) %eax)
17634         (write-buffered *(ebp+0x14) ": too many inouts\n")
17635         (flush *(ebp+0x14))
17636         (stop *(ebp+0x18) 1)
17637       }
17638       # if (expected == 0) error("too few inouts")
17639       {
17640         81 7/subop/compare %edx 0/imm32
17641         0f 84/jump-if-= break/disp32
17642         (write-buffered *(ebp+0x14) "fn ")
17643         8b/-> *(ebp+0x10) 0/r32/eax
17644         (lookup *eax *(eax+4))  # Function-name Function-name => eax
17645         (write-buffered *(ebp+0x14) %eax)
17646         (write-buffered *(ebp+0x14) ": call ")
17647         (lookup *edi *(edi+4))  # Function-name Function-name => eax
17648         (write-buffered *(ebp+0x14) %eax)
17649         (write-buffered *(ebp+0x14) ": too few inouts\n")
17650         (flush *(ebp+0x14))
17651         (stop *(ebp+0x18) 1)
17652       }
17653     }
17654 $check-mu-call:check-outputs:
17655     # var outputs/ecx: (addr stmt-var) = lookup(stmt->outputs)
17656     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
17657     89/<- %ecx 0/r32/eax
17658     # var expected/edx: (addr list var) = lookup(f->outputs)
17659     (lookup *(edi+0x10) *(edi+0x14))  # Function-outputs Function-outputs => eax
17660     89/<- %edx 0/r32/eax
17661     {
17662 $check-mu-call:check-for-outputs:
17663       # if (outputs == 0) break
17664       81 7/subop/compare %ecx 0/imm32
17665       0f 84/jump-if-= break/disp32
17666       # if (expected == 0) error
17667       81 7/subop/compare %edx 0/imm32
17668       0f 84/jump-if-= break/disp32
17669 $check-mu-call:check-output-type:
17670       # var v/eax: (addr v) = lookup(outputs->value)
17671       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
17672       # var t/ebx: (addr type-tree) = lookup(v->type)
17673       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
17674       89/<- %ebx 0/r32/eax
17675       # if (outputs->is-deref?) t = t->right  # TODO: check that t->left is an addr
17676       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
17677       {
17678         74/jump-if-= break/disp8
17679         (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
17680         89/<- %ebx 0/r32/eax
17681       }
17682       # var v2/eax: (addr v) = lookup(expected->value)
17683       (lookup *edx *(edx+4))  # List-value List-value => eax
17684       # var t2/eax: (addr type-tree) = lookup(v2->type)
17685       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
17686       # if (t != t2) error
17687       (type-match? %eax %ebx *(ebp-4))  # => eax
17688       3d/compare-eax-and 0/imm32/false
17689       {
17690         0f 85/jump-if-!= break/disp32
17691         (write-buffered *(ebp+0x14) "fn ")
17692         8b/-> *(ebp+0x10) 0/r32/eax
17693         (lookup *eax *(eax+4))  # Function-name Function-name => eax
17694         (write-buffered *(ebp+0x14) %eax)
17695         (write-buffered *(ebp+0x14) ": call ")
17696         (lookup *edi *(edi+4))  # Function-name Function-name => eax
17697         (write-buffered *(ebp+0x14) %eax)
17698         (write-buffered *(ebp+0x14) ": type for output '")
17699         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
17700         (lookup *eax *(eax+4))  # Var-name Var-name => eax
17701         (write-buffered *(ebp+0x14) %eax)
17702         (write-buffered *(ebp+0x14) "' is not right\n")
17703         (flush *(ebp+0x14))
17704         (stop *(ebp+0x18) 1)
17705       }
17706 $check-mu-call:check-output-register:
17707       # var v/eax: (addr v) = lookup(outputs->value)
17708       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
17709       # var r/ebx: (addr array byte) = lookup(v->register)
17710       (lookup *(eax+18) *(eax+0x1c))  # Var-register Var-register => eax
17711       89/<- %ebx 0/r32/eax
17712       # if (r == 0) error
17713       3d/compare-eax-and 0/imm32
17714       {
17715         0f 85/jump-if-!= break/disp32
17716         (write-buffered *(ebp+0x14) "fn ")
17717         8b/-> *(ebp+0x10) 0/r32/eax
17718         (lookup *eax *(eax+4))  # Function-name Function-name => eax
17719         (write-buffered *(ebp+0x14) %eax)
17720         (write-buffered *(ebp+0x14) ": call ")
17721         (lookup *edi *(edi+4))  # Function-name Function-name => eax
17722         (write-buffered *(ebp+0x14) %eax)
17723         (write-buffered *(ebp+0x14) ": output '")
17724         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
17725         (lookup *eax *(eax+4))  # Var-name Var-name => eax
17726         (write-buffered *(ebp+0x14) %eax)
17727         (write-buffered *(ebp+0x14) "' is not in a register\n")
17728         (flush *(ebp+0x14))
17729         (stop *(ebp+0x18) 1)
17730       }
17731       # var v2/eax: (addr v) = lookup(expected->value)
17732       (lookup *edx *(edx+4))  # Stmt-var-value Stmt-var-value => eax
17733       # var r2/eax: (addr array byte) = lookup(v2->register)
17734       (lookup *(eax+18) *(eax+0x1c))  # Var-register Var-register => eax
17735       # if (r != r2) error
17736       (string-equal? %eax %ebx)  # => eax
17737       3d/compare-eax-and 0/imm32/false
17738       {
17739         0f 85/jump-if-!= break/disp32
17740         (write-buffered *(ebp+0x14) "fn ")
17741         8b/-> *(ebp+0x10) 0/r32/eax
17742         (lookup *eax *(eax+4))  # Function-name Function-name => eax
17743         (write-buffered *(ebp+0x14) %eax)
17744         (write-buffered *(ebp+0x14) ": call ")
17745         (lookup *edi *(edi+4))  # Function-name Function-name => eax
17746         (write-buffered *(ebp+0x14) %eax)
17747         (write-buffered *(ebp+0x14) ": register for output '")
17748         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
17749         (lookup *eax *(eax+4))  # Var-name Var-name => eax
17750         (write-buffered *(ebp+0x14) %eax)
17751         (write-buffered *(ebp+0x14) "' is not right\n")
17752         (flush *(ebp+0x14))
17753         (stop *(ebp+0x18) 1)
17754       }
17755 $check-mu-call:continue-to-next-output:
17756       # outputs = lookup(outputs->next)
17757       (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
17758       89/<- %ecx 0/r32/eax
17759       # expected = lookup(expected->next)
17760       (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
17761       89/<- %edx 0/r32/eax
17762       #
17763       e9/jump loop/disp32
17764     }
17765 $check-mu-call:check-output-count:
17766     # if (outputs == expected) proceed
17767     39/compare %ecx 2/r32/edx
17768     {
17769       0f 84/jump-if-= break/disp32
17770       # exactly one of the two is null
17771       # if (outputs == 0) error("too many outputs")
17772       {
17773         81 7/subop/compare %ecx 0/imm32
17774         0f 84/jump-if-= break/disp32
17775         (write-buffered *(ebp+0x14) "fn ")
17776         8b/-> *(ebp+0x10) 0/r32/eax
17777         (lookup *eax *(eax+4))  # Function-name Function-name => eax
17778         (write-buffered *(ebp+0x14) %eax)
17779         (write-buffered *(ebp+0x14) ": call ")
17780         (lookup *edi *(edi+4))  # Function-name Function-name => eax
17781         (write-buffered *(ebp+0x14) %eax)
17782         (write-buffered *(ebp+0x14) ": too many outputs\n")
17783         (flush *(ebp+0x14))
17784         (stop *(ebp+0x18) 1)
17785       }
17786       # if (expected == 0) error("too few outputs")
17787       {
17788         81 7/subop/compare %edx 0/imm32
17789         0f 84/jump-if-= break/disp32
17790         (write-buffered *(ebp+0x14) "fn ")
17791         8b/-> *(ebp+0x10) 0/r32/eax
17792         (lookup *eax *(eax+4))  # Function-name Function-name => eax
17793         (write-buffered *(ebp+0x14) %eax)
17794         (write-buffered *(ebp+0x14) ": call ")
17795         (lookup *edi *(edi+4))  # Function-name Function-name => eax
17796         (write-buffered *(ebp+0x14) %eax)
17797         (write-buffered *(ebp+0x14) ": too few outputs\n")
17798         (flush *(ebp+0x14))
17799         (stop *(ebp+0x18) 1)
17800       }
17801     }
17802 $check-mu-call:end:
17803     # . restore registers
17804     5f/pop-to-edi
17805     5e/pop-to-esi
17806     5b/pop-to-ebx
17807     5a/pop-to-edx
17808     59/pop-to-ecx
17809     58/pop-to-eax
17810     # . reclaim locals exclusively on the stack
17811     81 0/subop/add %esp 0x70/imm32
17812     # . epilogue
17813     89/<- %esp 5/r32/ebp
17814     5d/pop-to-ebp
17815     c3/return
17816 
17817 # like type-equal? but takes literals into account
17818 type-match?:  # def: (addr type-tree), call: (addr type-tree), type-parameters: (addr table (handle array byte) (addr type-tree)) -> result/eax: boolean
17819     # . prologue
17820     55/push-ebp
17821     89/<- %ebp 4/r32/esp
17822     # if (call == literal) return true  # TODO: more precise
17823     (is-simple-mu-type? *(ebp+0xc) 0)  # literal => eax
17824     3d/compare-eax-and 0/imm32/false
17825     b8/copy-to-eax 1/imm32/true
17826     75/jump-if-!= $type-match?:end/disp8
17827 $type-match?:baseline:
17828     # otherwise fall back
17829     (type-component-match? *(ebp+8) *(ebp+0xc) *(ebp+0x10))  # => eax
17830 $type-match?:end:
17831     # . epilogue
17832     89/<- %esp 5/r32/ebp
17833     5d/pop-to-ebp
17834     c3/return
17835 
17836 type-component-match?:  # def: (addr type-tree), call: (addr type-tree), type-parameters: (addr table (handle array byte) (addr type-tree)) -> result/eax: boolean
17837     # . prologue
17838     55/push-ebp
17839     89/<- %ebp 4/r32/esp
17840     # . save registers
17841     51/push-ecx
17842     52/push-edx
17843     53/push-ebx
17844     # ecx = def
17845     8b/-> *(ebp+8) 1/r32/ecx
17846     # edx = call
17847     8b/-> *(ebp+0xc) 2/r32/edx
17848 $type-component-match?:compare-addr:
17849     # if (def == call) return true
17850     8b/-> %ecx 0/r32/eax  # Var-type
17851     39/compare %edx 0/r32/eax  # Var-type
17852     b8/copy-to-eax 1/imm32/true
17853     0f 84/jump-if-= $type-component-match?:end/disp32
17854     # if (def == 0) return false
17855     b8/copy-to-eax 0/imm32/false
17856     81 7/subop/compare %ecx 0/imm32  # Type-tree-is-atom
17857     0f 84/jump-if-= $type-component-match?:end/disp32
17858     # if (call == 0) return false
17859     81 7/subop/compare %edx 0/imm32  # Type-tree-is-atom
17860     0f 84/jump-if-= $type-component-match?:end/disp32
17861     # if def is a type parameter, just check in type-parameters
17862     {
17863 $type-component-match?:check-type-parameter:
17864       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
17865       74/jump-if-= break/disp8
17866       81 7/subop/compare *(ecx+4) 0xa/imm32/type-parameter  # Type-tree-value
17867       75/jump-if-!= break/disp8
17868 $type-component-match?:type-parameter:
17869       (type-parameter-match? *(ecx+8) *(ecx+0xc)  %edx  *(ebp+0x10))  # => eax
17870       e9/jump $type-component-match?:end/disp32
17871     }
17872     # if def is a list containing just a type parameter, just check in type-parameters
17873     {
17874 $type-component-match?:check-list-type-parameter:
17875       # if def is a list..
17876       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
17877       75/jump-if-!= break/disp8
17878       #   ..that's a singleton
17879       81 7/subop/compare *(ecx+0xc) 0/imm32  # Type-tree-left
17880       75/jump-if-!= break/disp8
17881       #   ..and whose head is a type parameter
17882       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
17883       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
17884       74/jump-if-= break/disp8
17885       81 7/subop/compare *(eax+4) 0xa/imm32/type-parameter  # Type-tree-value
17886       75/jump-if-!= break/disp8
17887 $type-component-match?:list-type-parameter:
17888       (type-parameter-match? *(eax+8) *(eax+0xc)  %edx  *(ebp+0x10))  # => eax
17889       e9/jump $type-component-match?:end/disp32
17890     }
17891 $type-component-match?:compare-atom-state:
17892     # if (def->is-atom? != call->is-atom?) return false
17893     8b/-> *ecx 3/r32/ebx  # Type-tree-is-atom
17894     39/compare *edx 3/r32/ebx  # Type-tree-is-atom
17895     b8/copy-to-eax 0/imm32/false
17896     0f 85/jump-if-!= $type-component-match?:end/disp32
17897     # if def->is-atom? return (def->value == call->value)
17898     {
17899 $type-component-match?:check-atom:
17900       81 7/subop/compare %ebx 0/imm32/false
17901       74/jump-if-= break/disp8
17902 $type-component-match?:is-atom:
17903       8b/-> *(ecx+4) 0/r32/eax  # Type-tree-value
17904       39/compare *(edx+4) 0/r32/eax  # Type-tree-value
17905       0f 94/set-if-= %al
17906       81 4/subop/and %eax 0xff/imm32
17907       e9/jump $type-component-match?:end/disp32
17908     }
17909 $type-component-match?:check-left:
17910     # if (!type-component-match?(def->left, call->left)) return false
17911     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
17912     89/<- %ebx 0/r32/eax
17913     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
17914     (type-component-match? %ebx %eax *(ebp+0x10))  # => eax
17915     3d/compare-eax-and 0/imm32/false
17916     74/jump-if-= $type-component-match?:end/disp8
17917 $type-component-match?:check-right:
17918     # return type-component-match?(def->right, call->right)
17919     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
17920     89/<- %ebx 0/r32/eax
17921     (lookup *(edx+0xc) *(edx+0x10))  # Type-tree-right Type-tree-right => eax
17922     (type-component-match? %ebx %eax *(ebp+0x10))  # => eax
17923 $type-component-match?:end:
17924     # . restore registers
17925     5b/pop-to-ebx
17926     5a/pop-to-edx
17927     59/pop-to-ecx
17928     # . epilogue
17929     89/<- %esp 5/r32/ebp
17930     5d/pop-to-ebp
17931     c3/return
17932 
17933 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
17934     # . prologue
17935     55/push-ebp
17936     89/<- %ebp 4/r32/esp
17937     # . save registers
17938     51/push-ecx
17939     #
17940     (get-or-insert-handle *(ebp+0x14)  *(ebp+8) *(ebp+0xc)  0xc)  # => eax
17941     # if parameter wasn't saved, save it
17942     {
17943       81 7/subop/compare *eax 0/imm32
17944       75/jump-if-!= break/disp8
17945       8b/-> *(ebp+0x10) 1/r32/ecx
17946       89/<- *eax 1/r32/ecx
17947     }
17948     #
17949     (type-equal? *(ebp+0x10) *eax)  # => eax
17950 $type-parameter-match?:end:
17951     # . restore registers
17952     59/pop-to-ecx
17953     # . epilogue
17954     89/<- %esp 5/r32/ebp
17955     5d/pop-to-ebp
17956     c3/return
17957 
17958 size-of:  # v: (addr var) -> result/eax: int
17959     # . prologue
17960     55/push-ebp
17961     89/<- %ebp 4/r32/esp
17962     # . save registers
17963     51/push-ecx
17964     # var t/ecx: (addr type-tree) = lookup(v->type)
17965     8b/-> *(ebp+8) 1/r32/ecx
17966 #?     (write-buffered Stderr "size-of ")
17967 #?     (write-int32-hex-buffered Stderr %ecx)
17968 #?     (write-buffered Stderr Newline)
17969 #?     (write-buffered Stderr "type allocid: ")
17970 #?     (write-int32-hex-buffered Stderr *(ecx+8))
17971 #?     (write-buffered Stderr Newline)
17972 #?     (flush Stderr)
17973     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
17974     89/<- %ecx 0/r32/eax
17975     # if is-mu-array?(t) return size-of-array(t)
17976     {
17977       (is-mu-array? %ecx)  # => eax
17978       3d/compare-eax-and 0/imm32/false
17979       74/jump-if-= break/disp8
17980       (size-of-array %ecx)  # => eax
17981       eb/jump $size-of:end/disp8
17982     }
17983     # if is-mu-stream?(t) return size-of-stream(t)
17984     {
17985       (is-mu-stream? %ecx)  # => eax
17986       3d/compare-eax-and 0/imm32/false
17987       74/jump-if-= break/disp8
17988       (size-of-stream %ecx)  # => eax
17989       eb/jump $size-of:end/disp8
17990     }
17991     # if (!t->is-atom?) t = lookup(t->left)
17992     {
17993       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
17994       75/jump-if-!= break/disp8
17995       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
17996       89/<- %ecx 0/r32/eax
17997     }
17998     # TODO: assert t->is-atom?
17999     (size-of-type-id *(ecx+4))  # Type-tree-value => eax
18000 $size-of:end:
18001     # . restore registers
18002     59/pop-to-ecx
18003     # . epilogue
18004     89/<- %esp 5/r32/ebp
18005     5d/pop-to-ebp
18006     c3/return
18007 
18008 size-of-deref:  # v: (addr var) -> result/eax: int
18009     # . prologue
18010     55/push-ebp
18011     89/<- %ebp 4/r32/esp
18012     # . save registers
18013     51/push-ecx
18014     # var t/ecx: (addr type-tree) = lookup(v->type)
18015     8b/-> *(ebp+8) 1/r32/ecx
18016     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
18017     89/<- %ecx 0/r32/eax
18018     # TODO: assert(t is an addr)
18019     # t = lookup(t->right)
18020     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
18021     89/<- %ecx 0/r32/eax
18022     # if is-mu-array?(t) return size-of-array(t)
18023     {
18024       (is-mu-array? %ecx)  # => eax
18025       3d/compare-eax-and 0/imm32/false
18026       74/jump-if-= break/disp8
18027       (size-of-array %ecx)  # => eax
18028       eb/jump $size-of-deref:end/disp8
18029     }
18030     # if is-mu-stream?(t) return size-of-stream(t)
18031     {
18032       (is-mu-stream? %ecx)  # => eax
18033       3d/compare-eax-and 0/imm32/false
18034       74/jump-if-= break/disp8
18035       (size-of-stream %ecx)  # => eax
18036       eb/jump $size-of-deref:end/disp8
18037     }
18038     # if (!t->is-atom?) t = lookup(t->left)
18039     {
18040       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
18041       75/jump-if-!= break/disp8
18042       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
18043       89/<- %ecx 0/r32/eax
18044     }
18045     # TODO: assert t->is-atom?
18046     (size-of-type-id *(ecx+4))  # Type-tree-value => eax
18047 $size-of-deref:end:
18048     # . restore registers
18049     59/pop-to-ecx
18050     # . epilogue
18051     89/<- %esp 5/r32/ebp
18052     5d/pop-to-ebp
18053     c3/return
18054 
18055 is-mu-array?:  # t: (addr type-tree) -> result/eax: boolean
18056     # . prologue
18057     55/push-ebp
18058     89/<- %ebp 4/r32/esp
18059     # . save registers
18060     51/push-ecx
18061     # ecx = t
18062     8b/-> *(ebp+8) 1/r32/ecx
18063     # if t->is-atom?, return false
18064     81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
18065     75/jump-if-!= $is-mu-array?:return-false/disp8
18066     # if !t->left->is-atom?, return false
18067     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
18068     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
18069     74/jump-if-= $is-mu-array?:return-false/disp8
18070     # return t->left->value == array
18071     81 7/subop/compare *(eax+4) 3/imm32/array-type-id  # Type-tree-value
18072     0f 94/set-if-= %al
18073     81 4/subop/and %eax 0xff/imm32
18074     eb/jump $is-mu-array?:end/disp8
18075 $is-mu-array?:return-false:
18076     b8/copy-to-eax 0/imm32/false
18077 $is-mu-array?:end:
18078     # . restore registers
18079     59/pop-to-ecx
18080     # . epilogue
18081     89/<- %esp 5/r32/ebp
18082     5d/pop-to-ebp
18083     c3/return
18084 
18085 # size of a statically allocated array where the size is part of the type expression
18086 size-of-array:  # a: (addr type-tree) -> result/eax: int
18087     # . prologue
18088     55/push-ebp
18089     89/<- %ebp 4/r32/esp
18090     # . save registers
18091     51/push-ecx
18092     52/push-edx
18093     #
18094     8b/-> *(ebp+8) 1/r32/ecx
18095     # TODO: assert that a->left is 'array'
18096     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
18097     89/<- %ecx 0/r32/eax
18098     # var elem-type/edx: type-id = a->right->left->value
18099     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
18100     8b/-> *(eax+4) 2/r32/edx  # Type-tree-value
18101     # TODO: assert that a->right->right->left->value == size
18102     # var array-size/ecx: int = a->right->right->left->value-size
18103     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
18104     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
18105     8b/-> *(eax+8) 1/r32/ecx  # Type-tree-value-size
18106     # return 4 + array-size * size-of(elem-type)
18107     (size-of-type-id-as-array-element %edx)  # => eax
18108     f7 4/subop/multiply-into-edx-eax %ecx
18109     05/add-to-eax 4/imm32  # for array size
18110     # TODO: check edx for overflow
18111 $size-of-array:end:
18112     # . restore registers
18113     5a/pop-to-edx
18114     59/pop-to-ecx
18115     # . epilogue
18116     89/<- %esp 5/r32/ebp
18117     5d/pop-to-ebp
18118     c3/return
18119 
18120 is-mu-stream?:  # t: (addr type-tree) -> result/eax: boolean
18121     # . prologue
18122     55/push-ebp
18123     89/<- %ebp 4/r32/esp
18124     # . save registers
18125     51/push-ecx
18126     # ecx = t
18127     8b/-> *(ebp+8) 1/r32/ecx
18128     # if t->is-atom?, return false
18129     81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
18130     75/jump-if-!= $is-mu-stream?:return-false/disp8
18131     # if !t->left->is-atom?, return false
18132     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
18133     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
18134     74/jump-if-= $is-mu-stream?:return-false/disp8
18135     # return t->left->value == stream
18136     81 7/subop/compare *(eax+4) 0xb/imm32/stream-type-id  # Type-tree-value
18137     0f 94/set-if-= %al
18138     81 4/subop/and %eax 0xff/imm32
18139     eb/jump $is-mu-stream?:end/disp8
18140 $is-mu-stream?:return-false:
18141     b8/copy-to-eax 0/imm32/false
18142 $is-mu-stream?:end:
18143     # . restore registers
18144     59/pop-to-ecx
18145     # . epilogue
18146     89/<- %esp 5/r32/ebp
18147     5d/pop-to-ebp
18148     c3/return
18149 
18150 # size of a statically allocated stream where the size is part of the type expression
18151 size-of-stream:  # a: (addr type-tree) -> result/eax: int
18152     # . prologue
18153     55/push-ebp
18154     89/<- %ebp 4/r32/esp
18155     #
18156     (size-of-array *(ebp+8))  # assumes we ignore the actual type name 'array' in the type
18157     05/add-to-eax 8/imm32  # for read/write pointers
18158 $size-of-stream:end:
18159     # . epilogue
18160     89/<- %esp 5/r32/ebp
18161     5d/pop-to-ebp
18162     c3/return
18163 
18164 size-of-type-id:  # t: type-id -> result/eax: int
18165     # . prologue
18166     55/push-ebp
18167     89/<- %ebp 4/r32/esp
18168     # . save registers
18169     51/push-ecx
18170     # var out/ecx: (handle typeinfo)
18171     68/push 0/imm32
18172     68/push 0/imm32
18173     89/<- %ecx 4/r32/esp
18174     # eax = t
18175     8b/-> *(ebp+8) 0/r32/eax
18176     # if t is a literal, return 0
18177     3d/compare-eax-and 0/imm32
18178     0f 84/jump-if-= $size-of-type-id:end/disp32  # eax changes type from type-id to int
18179     # if t is a byte, return 4 (because we don't really support non-multiples of 4)
18180     3d/compare-eax-and 8/imm32/byte
18181     {
18182       75/jump-if-!= break/disp8
18183       b8/copy-to-eax 4/imm32
18184       eb/jump $size-of-type-id:end/disp8
18185     }
18186     # if t is a handle, return 8
18187     3d/compare-eax-and 4/imm32/handle
18188     {
18189       75/jump-if-!= break/disp8
18190       b8/copy-to-eax 8/imm32
18191       eb/jump $size-of-type-id:end/disp8  # eax changes type from type-id to int
18192     }
18193     # if t is a slice, return 8
18194     3d/compare-eax-and 0xc/imm32/slice
18195     {
18196       75/jump-if-!= break/disp8
18197       b8/copy-to-eax 8/imm32
18198       eb/jump $size-of-type-id:end/disp8  # eax changes type from type-id to int
18199     }
18200     # if t is a user-defined type, return its size
18201     # TODO: support non-atom type
18202     (find-typeinfo %eax %ecx)
18203     {
18204       81 7/subop/compare *ecx 0/imm32
18205       74/jump-if-= break/disp8
18206 $size-of-type-id:user-defined:
18207       (lookup *ecx *(ecx+4))  # => eax
18208       8b/-> *(eax+0xc) 0/r32/eax  # Typeinfo-total-size-in-bytes
18209       eb/jump $size-of-type-id:end/disp8
18210     }
18211     # otherwise return the word size
18212     b8/copy-to-eax 4/imm32
18213 $size-of-type-id:end:
18214     # . reclaim locals
18215     81 0/subop/add %esp 8/imm32
18216     # . restore registers
18217     59/pop-to-ecx
18218     # . epilogue
18219     89/<- %esp 5/r32/ebp
18220     5d/pop-to-ebp
18221     c3/return
18222 
18223 # Minor violation of our type system since it returns an addr. But we could
18224 # replace it with a handle some time.
18225 # Returns null if t is an atom.
18226 type-tail:  # t: (addr type-tree) -> out/eax: (addr type-tree)
18227     # . prologue
18228     55/push-ebp
18229     89/<- %ebp 4/r32/esp
18230     # . save registers
18231     51/push-ecx
18232     # eax = 0
18233     b8/copy-to-eax 0/imm32
18234     # ecx = t
18235     8b/-> *(ebp+8) 1/r32/ecx
18236 $type-tail:check-atom:
18237     # if t->is-atom? return 0
18238     81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
18239     0f 85/jump-if-!= $type-tail:end/disp32
18240     # var tail = t->right
18241     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
18242     89/<- %ecx 0/r32/eax
18243 $type-tail:check-singleton:
18244     # if (tail->right == 0) return tail->left
18245     {
18246       81 7/subop/compare *(ecx+0xc) 0/imm32  # Type-tree-right
18247       75/jump-if-!= break/disp8
18248       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
18249       e9/jump $type-tail:end/disp32
18250     }
18251     # if tail->right->left is an array-capacity, return tail->left
18252     {
18253 $type-tail:check-array-capacity:
18254       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
18255       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
18256       75/jump-if-!= break/disp8
18257 $type-tail:check-array-capacity-1:
18258       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
18259       3d/compare-eax-and 0/imm32
18260       74/jump-if-= break/disp8
18261 $type-tail:check-array-capacity-2:
18262       (is-simple-mu-type? %eax 9)  # array-capacity => eax
18263       3d/compare-eax-and 0/imm32/false
18264       74/jump-if-= break/disp8
18265 $type-tail:array-capacity:
18266       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
18267       eb/jump $type-tail:end/disp8
18268     }
18269 $type-tail:check-compound-left:
18270     # if !tail->left->is-atom? return tail->left
18271     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
18272     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
18273     74/jump-if-= $type-tail:end/disp8
18274 $type-tail:return-tail:
18275     # return tail
18276     89/<- %eax 1/r32/ecx
18277 $type-tail:end:
18278     # . restore registers
18279     59/pop-to-ecx
18280     # . epilogue
18281     89/<- %esp 5/r32/ebp
18282     5d/pop-to-ebp
18283     c3/return
18284 
18285 type-equal?:  # a: (addr type-tree), b: (addr type-tree) -> result/eax: boolean
18286     # . prologue
18287     55/push-ebp
18288     89/<- %ebp 4/r32/esp
18289     # . save registers
18290     51/push-ecx
18291     52/push-edx
18292     53/push-ebx
18293     # ecx = a
18294     8b/-> *(ebp+8) 1/r32/ecx
18295     # edx = b
18296     8b/-> *(ebp+0xc) 2/r32/edx
18297 $type-equal?:compare-addr:
18298     # if (a == b) return true
18299     8b/-> %ecx 0/r32/eax  # Var-type
18300     39/compare %edx 0/r32/eax  # Var-type
18301     b8/copy-to-eax 1/imm32/true
18302     0f 84/jump-if-= $type-equal?:end/disp32
18303 $type-equal?:compare-null-a:
18304     # if (a == 0) return false
18305     b8/copy-to-eax 0/imm32/false
18306     81 7/subop/compare %ecx 0/imm32
18307     0f 84/jump-if-= $type-equal?:end/disp32
18308 $type-equal?:compare-null-b:
18309     # if (b == 0) return false
18310     81 7/subop/compare %edx 0/imm32
18311     0f 84/jump-if-= $type-equal?:end/disp32
18312 $type-equal?:compare-atom-state:
18313     # if (a->is-atom? != b->is-atom?) return false
18314     8b/-> *ecx 3/r32/ebx  # Type-tree-is-atom
18315     39/compare *edx 3/r32/ebx  # Type-tree-is-atom
18316     b8/copy-to-eax 0/imm32/false
18317     0f 85/jump-if-!= $type-equal?:end/disp32
18318     # if a->is-atom? return (a->value == b->value)
18319     {
18320 $type-equal?:check-atom:
18321       81 7/subop/compare %ebx 0/imm32/false
18322       74/jump-if-= break/disp8
18323 $type-equal?:is-atom:
18324       8b/-> *(ecx+4) 0/r32/eax  # Type-tree-value
18325       39/compare *(edx+4) 0/r32/eax  # Type-tree-value
18326       0f 94/set-if-= %al
18327       81 4/subop/and %eax 0xff/imm32
18328       e9/jump $type-equal?:end/disp32
18329     }
18330 $type-equal?:check-left:
18331     # if (!type-equal?(a->left, b->left)) return false
18332     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
18333     89/<- %ebx 0/r32/eax
18334     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
18335     (type-equal? %eax %ebx)  # => eax
18336     3d/compare-eax-and 0/imm32/false
18337     74/jump-if-= $type-equal?:end/disp8
18338 $type-equal?:check-right:
18339     # return type-equal?(a->right, b->right)
18340     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
18341     89/<- %ebx 0/r32/eax
18342     (lookup *(edx+0xc) *(edx+0x10))  # Type-tree-right Type-tree-right => eax
18343     (type-equal? %eax %ebx)  # => eax
18344 $type-equal?:end:
18345     # . restore registers
18346     5b/pop-to-ebx
18347     5a/pop-to-edx
18348     59/pop-to-ecx
18349     # . epilogue
18350     89/<- %esp 5/r32/ebp
18351     5d/pop-to-ebp
18352     c3/return
18353 
18354 #######################################################
18355 # Code-generation
18356 #######################################################
18357 
18358 == data
18359 
18360 # Global state added to each var record when performing code-generation.
18361 Curr-local-stack-offset:  # (addr int)
18362     0/imm32
18363 
18364 == code
18365 
18366 emit-subx:  # out: (addr buffered-file), err: (addr buffered-file), ed: (addr exit-descriptor)
18367     # . prologue
18368     55/push-ebp
18369     89/<- %ebp 4/r32/esp
18370     # . save registers
18371     50/push-eax
18372     # var curr/eax: (addr function) = *Program->functions
18373     (lookup *_Program-functions *_Program-functions->payload)  # => eax
18374     {
18375       # if (curr == null) break
18376       3d/compare-eax-and 0/imm32
18377       0f 84/jump-if-= break/disp32
18378       (emit-subx-function *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10))
18379       # curr = lookup(curr->next)
18380       (lookup *(eax+0x20) *(eax+0x24))  # Function-next Function-next => eax
18381       e9/jump loop/disp32
18382     }
18383 $emit-subx:end:
18384     # . restore registers
18385     58/pop-to-eax
18386     # . epilogue
18387     89/<- %esp 5/r32/ebp
18388     5d/pop-to-ebp
18389     c3/return
18390 
18391 emit-subx-function:  # out: (addr buffered-file), f: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
18392     # . prologue
18393     55/push-ebp
18394     89/<- %ebp 4/r32/esp
18395     # some preprocessing
18396     (populate-mu-type-offsets-in-inouts *(ebp+0xc))
18397     # . save registers
18398     50/push-eax
18399     51/push-ecx
18400     52/push-edx
18401     # initialize some global state
18402     c7 0/subop/copy *Curr-block-depth 1/imm32  # Important: keep this in sync with the parse phase
18403     c7 0/subop/copy *Curr-local-stack-offset 0/imm32
18404     # ecx = f
18405     8b/-> *(ebp+0xc) 1/r32/ecx
18406     # var vars/edx: (stack (addr var) 256)
18407     81 5/subop/subtract %esp 0xc00/imm32
18408     68/push 0xc00/imm32/size
18409     68/push 0/imm32/top
18410     89/<- %edx 4/r32/esp
18411     # var name/eax: (addr array byte) = lookup(f->name)
18412     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
18413     #
18414     (write-buffered *(ebp+8) %eax)
18415     (write-buffered *(ebp+8) ":\n")
18416     (emit-subx-prologue *(ebp+8))
18417     # var body/eax: (addr block) = lookup(f->body)
18418     (lookup *(ecx+0x18) *(ecx+0x1c))  # Function-body Function-body => eax
18419     #
18420     (emit-subx-block *(ebp+8) %eax %edx *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
18421     (emit-subx-epilogue *(ebp+8))
18422     # TODO: validate that *Curr-block-depth and *Curr-local-stack-offset have
18423     # been cleaned up
18424 $emit-subx-function:end:
18425     # . reclaim locals
18426     81 0/subop/add %esp 0xc08/imm32
18427     # . restore registers
18428     5a/pop-to-edx
18429     59/pop-to-ecx
18430     58/pop-to-eax
18431     # . epilogue
18432     89/<- %esp 5/r32/ebp
18433     5d/pop-to-ebp
18434     c3/return
18435 
18436 populate-mu-type-offsets-in-inouts:  # f: (addr function)
18437     # . prologue
18438     55/push-ebp
18439     89/<- %ebp 4/r32/esp
18440     # . save registers
18441     50/push-eax
18442     51/push-ecx
18443     52/push-edx
18444     53/push-ebx
18445     57/push-edi
18446     # var next-offset/edx: int = 8
18447     ba/copy-to-edx 8/imm32
18448     # var curr/ecx: (addr list var) = lookup(f->inouts)
18449     8b/-> *(ebp+8) 1/r32/ecx
18450     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
18451     89/<- %ecx 0/r32/eax
18452     {
18453 $populate-mu-type-offsets-in-inouts:loop:
18454       81 7/subop/compare %ecx 0/imm32
18455       74/jump-if-= break/disp8
18456       # var v/ebx: (addr var) = lookup(curr->value)
18457       (lookup *ecx *(ecx+4))  # List-value List-value => eax
18458       89/<- %ebx 0/r32/eax
18459 #?       (lookup *ebx *(ebx+4))
18460 #?       (write-buffered Stderr "setting offset of fn inout ")
18461 #?       (write-buffered Stderr %eax)
18462 #?       (write-buffered Stderr "@")
18463 #?       (write-int32-hex-buffered Stderr %ebx)
18464 #?       (write-buffered Stderr " to ")
18465 #?       (write-int32-hex-buffered Stderr %edx)
18466 #?       (write-buffered Stderr Newline)
18467 #?       (flush Stderr)
18468       # v->offset = next-offset
18469       89/<- *(ebx+0x14) 2/r32/edx  # Var-offset
18470       # next-offset += size-of(v)
18471       (size-of %ebx)  # => eax
18472       01/add-to %edx 0/r32/eax
18473       # curr = lookup(curr->next)
18474       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
18475       89/<- %ecx 0/r32/eax
18476       #
18477       eb/jump loop/disp8
18478     }
18479 $populate-mu-type-offsets-in-inouts:end:
18480     # . restore registers
18481     5f/pop-to-edi
18482     5b/pop-to-ebx
18483     5a/pop-to-edx
18484     59/pop-to-ecx
18485     58/pop-to-eax
18486     # . epilogue
18487     89/<- %esp 5/r32/ebp
18488     5d/pop-to-ebp
18489     c3/return
18490 
18491 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)
18492     # . prologue
18493     55/push-ebp
18494     89/<- %ebp 4/r32/esp
18495     # . save registers
18496     50/push-eax
18497     51/push-ecx
18498     53/push-ebx
18499     56/push-esi
18500     # esi = stmts
18501     8b/-> *(ebp+0xc) 6/r32/esi
18502     #
18503     {
18504 $emit-subx-stmt-list:loop:
18505       81 7/subop/compare %esi 0/imm32
18506       0f 84/jump-if-= break/disp32
18507       # var curr-stmt/ecx: (addr stmt) = lookup(stmts->value)
18508       (lookup *esi *(esi+4))  # List-value List-value => eax
18509       89/<- %ecx 0/r32/eax
18510       {
18511 $emit-subx-stmt-list:check-for-block:
18512         81 7/subop/compare *ecx 0/imm32/block  # Stmt-tag
18513         75/jump-if-!= break/disp8
18514 $emit-subx-stmt-list:block:
18515         (emit-subx-block *(ebp+8) %ecx *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
18516       }
18517       {
18518 $emit-subx-stmt-list:check-for-stmt:
18519         81 7/subop/compare *ecx 1/imm32/stmt1  # Stmt-tag
18520         0f 85/jump-if-!= break/disp32
18521 $emit-subx-stmt-list:stmt1:
18522         {
18523           (is-mu-branch? %ecx)  # => eax
18524           3d/compare-eax-and 0/imm32/false
18525           0f 84/jump-if-= break/disp32
18526 $emit-subx-stmt-list:branch-stmt:
18527 +-- 25 lines: # unconditional return -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
18552 +-- 27 lines: # unconditional loops --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
18579 +-- 16 lines: # unconditional breaks -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
18595 +-- 38 lines: # simple conditional branches without a target -------------------------------------------------------------------------------------------------------------------------------------------------------
18633 +-- 19 lines: # conditional branches with an explicit target -------------------------------------------------------------------------------------------------------------------------------------------------------
18652         }
18653 $emit-subx-stmt-list:1-to-1:
18654         (emit-subx-stmt *(ebp+8) %ecx Primitives *(ebp+0x18) *(ebp+0x1c))
18655         e9/jump $emit-subx-stmt-list:continue/disp32
18656       }
18657       {
18658 $emit-subx-stmt-list:check-for-var-def:
18659         81 7/subop/compare *ecx 2/imm32/var-def  # Stmt-tag
18660         75/jump-if-!= break/disp8
18661 $emit-subx-stmt-list:var-def:
18662         (emit-subx-var-def *(ebp+8) %ecx)
18663         (push *(ebp+0x10) *(ecx+4))  # Vardef-var
18664         (push *(ebp+0x10) *(ecx+8))  # Vardef-var
18665         (push *(ebp+0x10) 0)  # Live-var-register-spilled = 0 for vars on the stack
18666         #
18667         eb/jump $emit-subx-stmt-list:continue/disp8
18668       }
18669       {
18670 $emit-subx-stmt-list:check-for-reg-var-def:
18671         81 7/subop/compare *ecx 3/imm32/reg-var-def  # Stmt-tag
18672         0f 85/jump-if-!= break/disp32
18673 $emit-subx-stmt-list:reg-var-def:
18674         # TODO: ensure that there's exactly one output
18675         (push-output-and-maybe-emit-spill *(ebp+8) %ecx *(ebp+0x10) %esi *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
18676         # emit the instruction as usual
18677         (emit-subx-stmt *(ebp+8) %ecx Primitives *(ebp+0x18) *(ebp+0x1c))
18678         #
18679         eb/jump $emit-subx-stmt-list:continue/disp8
18680       }
18681 $emit-subx-stmt-list:continue:
18682       # TODO: raise an error on unrecognized Stmt-tag
18683       (lookup *(esi+8) *(esi+0xc))  # List-next List-next => eax
18684       89/<- %esi 0/r32/eax
18685       e9/jump loop/disp32
18686     }
18687 $emit-subx-stmt-list:emit-cleanup:
18688     (emit-cleanup-code-until-depth *(ebp+8) *(ebp+0x10) *Curr-block-depth)
18689 $emit-subx-stmt-list:clean-up:
18690     (clean-up-stack-offset-state *(ebp+0x10) *Curr-block-depth)
18691     (clean-up-blocks *(ebp+0x10) *Curr-block-depth *(ebp+0x14))
18692 $emit-subx-stmt-list:end:
18693     # . restore registers
18694     5e/pop-to-esi
18695     5b/pop-to-ebx
18696     59/pop-to-ecx
18697     58/pop-to-eax
18698     # . epilogue
18699     89/<- %esp 5/r32/ebp
18700     5d/pop-to-ebp
18701     c3/return
18702 
18703 # 'later-stmts' includes 'stmt', but will behave the same even without it; reg-var-def stmts are guaranteed not to write to function outputs.
18704 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)
18705     # . prologue
18706     55/push-ebp
18707     89/<- %ebp 4/r32/esp
18708     # . save registers
18709     50/push-eax
18710     51/push-ecx
18711     52/push-edx
18712     # ecx = stmt
18713     8b/-> *(ebp+0xc) 1/r32/ecx
18714     # var sv/eax: (addr stmt-var) = lookup(curr-stmt->outputs)
18715     (lookup *(ecx+0x14) *(ecx+0x18))  # Regvardef-outputs Regvardef-outputs => eax
18716     # TODO: assert !sv->is-deref?
18717     # var v/ecx: (addr var) = lookup(sv->value)
18718     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
18719     89/<- %ecx 0/r32/eax
18720     # v->block-depth = *Curr-block-depth
18721     8b/-> *Curr-block-depth 0/r32/eax
18722     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
18723 #?     (write-buffered Stderr "var ")
18724 #?     (lookup *ecx *(ecx+4))
18725 #?     (write-buffered Stderr %eax)
18726 #?     (write-buffered Stderr " at depth ")
18727 #?     (write-int32-hex-buffered Stderr *(ecx+0x10))
18728 #?     (write-buffered Stderr Newline)
18729 #?     (flush Stderr)
18730     # ensure that v is in a register
18731     81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
18732     0f 84/jump-if-= $push-output-and-maybe-emit-spill:abort/disp32
18733     # var emit-spill?/edx: boolean = not-yet-spilled-this-block? && will-not-write-some-register?(fn)
18734     (not-yet-spilled-this-block? %ecx *(ebp+0x10))  # => eax
18735     89/<- %edx 0/r32/eax
18736     3d/compare-eax-and 0/imm32/false
18737     0f 84/jump-if-= $push-output-and-maybe-emit-spill:push/disp32
18738     (will-not-write-some-register? %ecx *(ebp+0x14) *(ebp+0x18))  # => eax
18739     89/<- %edx 0/r32/eax
18740     # check emit-spill?
18741     3d/compare-eax-and 0/imm32/false
18742     0f 84/jump-if-= $push-output-and-maybe-emit-spill:push/disp32
18743     # TODO: assert(size-of(output) == 4)
18744     # *Curr-local-stack-offset -= 4
18745     81 5/subop/subtract *Curr-local-stack-offset 4/imm32
18746     # emit spill
18747     (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
18748     (emit-push-register *(ebp+8) %eax)
18749 $push-output-and-maybe-emit-spill:push:
18750     8b/-> *(ebp+0xc) 1/r32/ecx
18751     (lookup *(ecx+0x14) *(ecx+0x18))  # Regvardef-outputs Regvardef-outputs => eax
18752     # push(vars, {sv->value, emit-spill?})
18753     (push *(ebp+0x10) *eax)  # Stmt-var-value
18754     (push *(ebp+0x10) *(eax+4))  # Stmt-var-value
18755     (push *(ebp+0x10) %edx)
18756 $push-output-and-maybe-emit-spill:end:
18757     # . restore registers
18758     5a/pop-to-edx
18759     59/pop-to-ecx
18760     58/pop-to-eax
18761     # . epilogue
18762     89/<- %esp 5/r32/ebp
18763     5d/pop-to-ebp
18764     c3/return
18765 
18766 $push-output-and-maybe-emit-spill:abort:
18767     # error("var '" var->name "' initialized from an instruction must live in a register\n")
18768     (write-buffered *(ebp+0x1c) "var '")
18769     (write-buffered *(ebp+0x1c) *eax)  # Var-name
18770     (write-buffered *(ebp+0x1c) "' initialized from an instruction must live in a register\n")
18771     (flush *(ebp+0x1c))
18772     (stop *(ebp+0x20) 1)
18773     # never gets here
18774 
18775 emit-subx-cleanup-and-unconditional-nonlocal-branch:  # out: (addr buffered-file), stmt: (addr stmt1), vars: (addr stack live-var)
18776     # . prologue
18777     55/push-ebp
18778     89/<- %ebp 4/r32/esp
18779     # . save registers
18780     50/push-eax
18781     51/push-ecx
18782     # ecx = stmt
18783     8b/-> *(ebp+0xc) 1/r32/ecx
18784     # var target/eax: (addr array byte) = curr-stmt->inouts->value->name
18785     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
18786     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
18787     (lookup *eax *(eax+4))  # Var-name Var-name => eax
18788     # clean up until target block
18789     (emit-cleanup-code-until-target *(ebp+8) *(ebp+0x10) %eax)
18790     # emit jump to target block
18791     (emit-indent *(ebp+8) *Curr-block-depth)
18792     (write-buffered *(ebp+8) "e9/jump ")
18793     (write-buffered *(ebp+8) %eax)
18794     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
18795     (string-starts-with? %eax "break")
18796     3d/compare-eax-and 0/imm32/false
18797     {
18798       74/jump-if-= break/disp8
18799       (write-buffered *(ebp+8) ":break/disp32\n")
18800       eb/jump $emit-subx-cleanup-and-unconditional-nonlocal-branch:end/disp8
18801     }
18802     (write-buffered *(ebp+8) ":loop/disp32\n")
18803 $emit-subx-cleanup-and-unconditional-nonlocal-branch:end:
18804     # . restore registers
18805     59/pop-to-ecx
18806     58/pop-to-eax
18807     # . epilogue
18808     89/<- %esp 5/r32/ebp
18809     5d/pop-to-ebp
18810     c3/return
18811 
18812 emit-outputs:  # out: (addr buffered-file), return-stmt: (addr stmt1), fn: (addr function)
18813     # pseudocode:
18814     #   for every inout, output in return-stmt, fn->outputs
18815     #     if inout is a literal
18816     #       c7 0/subop/copy %output inout/imm32
18817     #     otherwise
18818     #       8b/-> inout %output
18819     #
18820     # . prologue
18821     55/push-ebp
18822     89/<- %ebp 4/r32/esp
18823     # . save registers
18824     50/push-eax
18825     51/push-ecx
18826     56/push-esi
18827     57/push-edi
18828     # var curr-inout/esi: (addr stmt-var) = return-stmt->inouts
18829     8b/-> *(ebp+0xc) 0/r32/eax
18830     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
18831     89/<- %esi 0/r32/eax
18832     # var curr-output/edi: (addr list var) = fn->outputs
18833     8b/-> *(ebp+0x10) 0/r32/eax
18834     (lookup *(eax+0x10) *(eax+0x14))  # Function-outputs Function-outputs => eax
18835     89/<- %edi 0/r32/eax
18836     {
18837 $emit-outputs:loop:
18838       81 7/subop/compare %esi 0/imm32
18839       0f 84/jump-if-= break/disp32
18840       # emit copy to output register
18841       # var curr-var/ecx = lookup(curr-inout->value)
18842       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
18843       89/<- %ecx 0/r32/eax
18844       # if curr-var is a literal, emit copy of a literal to the output
18845       (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
18846       (is-simple-mu-type? %eax 0)  # literal => eax
18847       {
18848         3d/compare-eax-and 0/imm32/false
18849         0f 84/jump-if-= break/disp32
18850         (emit-indent *(ebp+8) *Curr-block-depth)
18851         (write-buffered *(ebp+8) "c7 0/subop/copy %")
18852         (lookup *edi *(edi+4))  # List-value List-value => eax
18853         (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
18854         (write-buffered *(ebp+8) %eax)
18855         (write-buffered *(ebp+8) " ")
18856         (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
18857         (write-buffered *(ebp+8) %eax)
18858         (write-buffered *(ebp+8) "/imm32\n")
18859         e9/jump $emit-outputs:continue/disp32
18860       }
18861       # if the non-literal is a register starting with "x", emit a floating-point copy
18862       (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
18863       {
18864         3d/compare-eax-and 0/imm32
18865         0f 84/jump-if-= break/disp32
18866         8a/copy-byte *(eax+4) 0/r32/AL
18867         81 4/subop/and %eax 0xff/imm32
18868         3d/compare-eax-and 0x78/imm32/x
18869         0f 85/jump-if-!= break/disp32
18870         (emit-indent *(ebp+8) *Curr-block-depth)
18871         (write-buffered *(ebp+8) "f3 0f 10/->")
18872         (emit-subx-var-as-rm32 *(ebp+8) %esi)
18873         (write-buffered *(ebp+8) " ")
18874         (lookup *edi *(edi+4))  # List-value List-value => eax
18875         (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
18876         (get Mu-registers %eax 0xc "Mu-registers")  # => eax
18877         (write-int32-hex-buffered *(ebp+8) *eax)
18878         (write-buffered *(ebp+8) "/x32\n")
18879         e9/jump $emit-outputs:continue/disp32
18880       }
18881       # otherwise emit an integer copy
18882       (emit-indent *(ebp+8) *Curr-block-depth)
18883       (write-buffered *(ebp+8) "8b/->")
18884       (emit-subx-var-as-rm32 *(ebp+8) %esi)
18885       (write-buffered *(ebp+8) " ")
18886       (lookup *edi *(edi+4))  # List-value List-value => eax
18887       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
18888       (get Mu-registers %eax 0xc "Mu-registers")  # => eax
18889       (write-int32-hex-buffered *(ebp+8) *eax)
18890       (write-buffered *(ebp+8) "/r32\n")
18891 $emit-outputs:continue:
18892       # curr-inout = curr-inout->next
18893       (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
18894       89/<- %esi 0/r32/eax
18895       # curr-output = curr-output->next
18896       (lookup *(edi+8) *(edi+0xc))  # List-next List-next => eax
18897       89/<- %edi 0/r32/eax
18898       #
18899       e9/jump loop/disp32
18900     }
18901 $emit-outputs:end:
18902     # . restore registers
18903     5f/pop-to-edi
18904     5e/pop-to-esi
18905     59/pop-to-ecx
18906     58/pop-to-eax
18907     # . epilogue
18908     89/<- %esp 5/r32/ebp
18909     5d/pop-to-ebp
18910     c3/return
18911 
18912 is-mu-branch?:  # stmt: (addr stmt1) -> result/eax: boolean
18913     # . prologue
18914     55/push-ebp
18915     89/<- %ebp 4/r32/esp
18916     # . save registers
18917     51/push-ecx
18918     # ecx = lookup(stmt->operation)
18919     8b/-> *(ebp+8) 1/r32/ecx
18920     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
18921     89/<- %ecx 0/r32/eax
18922     # if (stmt->operation starts with "loop") return true
18923     (string-starts-with? %ecx "loop")  # => eax
18924     3d/compare-eax-and 0/imm32/false
18925     75/jump-if-not-equal $is-mu-branch?:end/disp8
18926     # if (stmt->operation starts with "break") return true
18927     (string-starts-with? %ecx "break")  # => eax
18928     3d/compare-eax-and 0/imm32/false
18929     75/jump-if-not-equal $is-mu-branch?:end/disp8
18930     # otherwise return (stmt->operation starts with "return")
18931     (string-starts-with? %ecx "return")  # => eax
18932 $is-mu-branch?:end:
18933     # . restore registers
18934     59/pop-to-ecx
18935     # . epilogue
18936     89/<- %esp 5/r32/ebp
18937     5d/pop-to-ebp
18938     c3/return
18939 
18940 emit-reverse-break:  # out: (addr buffered-file), stmt: (addr stmt1)
18941     # . prologue
18942     55/push-ebp
18943     89/<- %ebp 4/r32/esp
18944     # . save registers
18945     50/push-eax
18946     # eax = stmt
18947     8b/-> *(ebp+0xc) 0/r32/eax
18948     #
18949     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
18950     (get Reverse-branch %eax 0x10 "reverse-branch: ")  # => eax: (addr handle array byte)
18951     (emit-indent *(ebp+8) *Curr-block-depth)
18952     (lookup *eax *(eax+4))  # => eax
18953     (write-buffered *(ebp+8) %eax)
18954     (write-buffered *(ebp+8) " break/disp32\n")
18955 $emit-reverse-break:end:
18956     # . restore registers
18957     58/pop-to-eax
18958     # . epilogue
18959     89/<- %esp 5/r32/ebp
18960     5d/pop-to-ebp
18961     c3/return
18962 
18963 == data
18964 
18965 # Table from Mu branch instructions to the reverse SubX opcodes for them.
18966 Reverse-branch:  # (table (handle array byte) (handle array byte))
18967   # a table is a stream
18968   0x1c0/imm32/write
18969   0/imm32/read
18970   0x1c0/imm32/size
18971   # data
18972   0x11/imm32/alloc-id   _string-break-if-=/imm32                0x11/imm32/alloc-id   _string_0f_85_jump_label/imm32
18973   0x11/imm32/alloc-id   _string-loop-if-=/imm32                 0x11/imm32/alloc-id   _string_0f_85_jump_label/imm32
18974   0x11/imm32/alloc-id   _string-break-if-!=/imm32               0x11/imm32/alloc-id   _string_0f_84_jump_label/imm32
18975   0x11/imm32/alloc-id   _string-loop-if-!=/imm32                0x11/imm32/alloc-id   _string_0f_84_jump_label/imm32
18976   0x11/imm32/alloc-id   _string-break-if-</imm32                0x11/imm32/alloc-id   _string_0f_8d_jump_label/imm32
18977   0x11/imm32/alloc-id   _string-loop-if-</imm32                 0x11/imm32/alloc-id   _string_0f_8d_jump_label/imm32
18978   0x11/imm32/alloc-id   _string-break-if->/imm32                0x11/imm32/alloc-id   _string_0f_8e_jump_label/imm32
18979   0x11/imm32/alloc-id   _string-loop-if->/imm32                 0x11/imm32/alloc-id   _string_0f_8e_jump_label/imm32
18980   0x11/imm32/alloc-id   _string-break-if-<=/imm32               0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
18981   0x11/imm32/alloc-id   _string-loop-if-<=/imm32                0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
18982   0x11/imm32/alloc-id   _string-break-if->=/imm32               0x11/imm32/alloc-id   _string_0f_8c_jump_label/imm32
18983   0x11/imm32/alloc-id   _string-loop-if->=/imm32                0x11/imm32/alloc-id   _string_0f_8c_jump_label/imm32
18984   0x11/imm32/alloc-id   _string-break-if-addr</imm32            0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
18985   0x11/imm32/alloc-id   _string-loop-if-addr</imm32             0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
18986   0x11/imm32/alloc-id   _string-break-if-addr>/imm32            0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
18987   0x11/imm32/alloc-id   _string-loop-if-addr>/imm32             0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
18988   0x11/imm32/alloc-id   _string-break-if-addr<=/imm32           0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
18989   0x11/imm32/alloc-id   _string-loop-if-addr<=/imm32            0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
18990   0x11/imm32/alloc-id   _string-break-if-addr>=/imm32           0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
18991   0x11/imm32/alloc-id   _string-loop-if-addr>=/imm32            0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
18992   0x11/imm32/alloc-id   _string-break-if-float</imm32           0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
18993   0x11/imm32/alloc-id   _string-loop-if-float</imm32            0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
18994   0x11/imm32/alloc-id   _string-break-if-float>/imm32           0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
18995   0x11/imm32/alloc-id   _string-loop-if-float>/imm32            0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
18996   0x11/imm32/alloc-id   _string-break-if-float<=/imm32          0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
18997   0x11/imm32/alloc-id   _string-loop-if-float<=/imm32           0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
18998   0x11/imm32/alloc-id   _string-break-if-float>=/imm32          0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
18999   0x11/imm32/alloc-id   _string-loop-if-float>=/imm32           0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
19000 
19001 == code
19002 
19003 emit-unconditional-jump-to-depth:  # out: (addr buffered-file), vars: (addr stack live-var), depth: int, label-suffix: (addr array byte)
19004     # . prologue
19005     55/push-ebp
19006     89/<- %ebp 4/r32/esp
19007     # . save registers
19008     50/push-eax
19009     51/push-ecx
19010     52/push-edx
19011     53/push-ebx
19012     56/push-esi
19013     # ecx = vars
19014     8b/-> *(ebp+0xc) 1/r32/ecx
19015     # var eax: int = vars->top
19016     8b/-> *ecx 0/r32/eax
19017     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
19018     8d/copy-address *(ecx+eax-4) 6/r32/esi  # vars + 8 + vars->top - 12/Live-var-size
19019     # var min/ecx: (addr handle var) = vars->data
19020     8d/copy-address *(ecx+8) 1/r32/ecx
19021     # edx = depth
19022     8b/-> *(ebp+0x10) 2/r32/edx
19023     {
19024 $emit-unconditional-jump-to-depth:loop:
19025       # if (curr < min) break
19026       39/compare %esi 1/r32/ecx
19027       0f 82/jump-if-addr< break/disp32
19028       # var v/ebx: (addr var) = lookup(*curr)
19029       (lookup *esi *(esi+4))  # => eax
19030       89/<- %ebx 0/r32/eax
19031       # if (v->block-depth < until-block-depth) break
19032       39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
19033       0f 8c/jump-if-< break/disp32
19034       {
19035 $emit-unconditional-jump-to-depth:check:
19036         # if v->block-depth != until-block-depth, continue
19037         39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
19038         0f 85/jump-if-!= break/disp32
19039 $emit-unconditional-jump-to-depth:depth-found:
19040         # if v is not a literal, continue
19041         (size-of %ebx)  # => eax
19042         3d/compare-eax-and 0/imm32
19043         0f 85/jump-if-!= break/disp32
19044 $emit-unconditional-jump-to-depth:label-found:
19045         # emit unconditional jump, then return
19046         (emit-indent *(ebp+8) *Curr-block-depth)
19047         (write-buffered *(ebp+8) "e9/jump ")
19048         (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
19049         (write-buffered *(ebp+8) %eax)
19050         (write-buffered *(ebp+8) ":")
19051         (write-buffered *(ebp+8) *(ebp+0x14))
19052         (write-buffered *(ebp+8) "/disp32\n")
19053         eb/jump $emit-unconditional-jump-to-depth:end/disp8
19054       }
19055       # curr -= 12
19056       81 5/subop/subtract %esi 0xc/imm32
19057       e9/jump loop/disp32
19058     }
19059     # TODO: error if no label at 'depth' was found
19060 $emit-unconditional-jump-to-depth:end:
19061     # . restore registers
19062     5e/pop-to-esi
19063     5b/pop-to-ebx
19064     5a/pop-to-edx
19065     59/pop-to-ecx
19066     58/pop-to-eax
19067     # . epilogue
19068     89/<- %esp 5/r32/ebp
19069     5d/pop-to-ebp
19070     c3/return
19071 
19072 # emit clean-up code for 'vars' until some block depth
19073 # doesn't actually modify 'vars' so we need traverse manually inside the stack
19074 emit-cleanup-code-until-depth:  # out: (addr buffered-file), vars: (addr stack live-var), until-block-depth: int
19075     # . prologue
19076     55/push-ebp
19077     89/<- %ebp 4/r32/esp
19078     # . save registers
19079     50/push-eax
19080     51/push-ecx
19081     52/push-edx
19082     53/push-ebx
19083     56/push-esi
19084 #?     (write-buffered Stderr "--- cleanup\n")
19085 #?     (flush Stderr)
19086     # ecx = vars
19087     8b/-> *(ebp+0xc) 1/r32/ecx
19088     # var esi: int = vars->top
19089     8b/-> *ecx 6/r32/esi
19090     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
19091     8d/copy-address *(ecx+esi-4) 6/r32/esi  # vars + 8 + vars->top - 12/Live-var-size
19092     # var min/ecx: (addr handle var) = vars->data
19093     81 0/subop/add %ecx 8/imm32
19094     # edx = until-block-depth
19095     8b/-> *(ebp+0x10) 2/r32/edx
19096     {
19097 $emit-cleanup-code-until-depth:loop:
19098       # if (curr < min) break
19099       39/compare %esi 1/r32/ecx
19100       0f 82/jump-if-addr< break/disp32
19101       # var v/ebx: (addr var) = lookup(*curr)
19102       (lookup *esi *(esi+4))  # => eax
19103       89/<- %ebx 0/r32/eax
19104 #?       (lookup *ebx *(ebx+4))  # Var-name
19105 #?       (write-buffered Stderr "var ")
19106 #?       (write-buffered Stderr %eax)
19107 #?       (write-buffered Stderr Newline)
19108 #?       (flush Stderr)
19109       # if (v->block-depth < until-block-depth) break
19110       39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
19111       0f 8c/jump-if-< break/disp32
19112       # if v is in a register
19113       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
19114       {
19115         0f 84/jump-if-= break/disp32
19116         {
19117 $emit-cleanup-code-until-depth:check-for-previous-spill:
19118           8b/-> *(esi+8) 0/r32/eax  # Live-var-register-spilled
19119           3d/compare-eax-and 0/imm32/false
19120           74/jump-if-= break/disp8
19121 $emit-cleanup-code-until-depth:reclaim-var-in-register:
19122           (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
19123           (emit-pop-register *(ebp+8) %eax)
19124         }
19125         eb/jump $emit-cleanup-code-until-depth:continue/disp8
19126       }
19127       # otherwise v is on the stack
19128       {
19129         75/jump-if-!= break/disp8
19130 $emit-cleanup-code-until-depth:var-on-stack:
19131         (size-of %ebx)  # => eax
19132         # don't emit code for labels
19133         3d/compare-eax-and 0/imm32
19134         74/jump-if-= break/disp8
19135 $emit-cleanup-code-until-depth:reclaim-var-on-stack:
19136         (emit-indent *(ebp+8) *Curr-block-depth)
19137         (write-buffered *(ebp+8) "81 0/subop/add %esp ")
19138         (write-int32-hex-buffered *(ebp+8) %eax)
19139         (write-buffered *(ebp+8) "/imm32\n")
19140       }
19141 $emit-cleanup-code-until-depth:continue:
19142       # curr -= 12
19143       81 5/subop/subtract %esi 0xc/imm32
19144       e9/jump loop/disp32
19145     }
19146 $emit-cleanup-code-until-depth:end:
19147     # . restore registers
19148     5e/pop-to-esi
19149     5b/pop-to-ebx
19150     5a/pop-to-edx
19151     59/pop-to-ecx
19152     58/pop-to-eax
19153     # . epilogue
19154     89/<- %esp 5/r32/ebp
19155     5d/pop-to-ebp
19156     c3/return
19157 
19158 # emit clean-up code for 'vars' that don't conflict with output registers
19159 # doesn't actually modify 'vars' so we need traverse manually inside the stack
19160 emit-cleanup-code-for-non-outputs:  # out: (addr buffered-file), vars: (addr stack live-var), fn: (addr function)
19161     # . prologue
19162     55/push-ebp
19163     89/<- %ebp 4/r32/esp
19164     # . save registers
19165     50/push-eax
19166     51/push-ecx
19167     52/push-edx
19168     53/push-ebx
19169     56/push-esi
19170     57/push-edi
19171     # ecx = vars
19172     8b/-> *(ebp+0xc) 1/r32/ecx
19173     # var esi: int = vars->top
19174     8b/-> *ecx 6/r32/esi
19175     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
19176     8d/copy-address *(ecx+esi-4) 6/r32/esi  # vars + 8 + vars->top - 12/Live-var-size
19177     # var min/ecx: (addr handle var) = vars->data
19178     81 0/subop/add %ecx 8/imm32
19179     {
19180 $emit-cleanup-code-for-non-outputs:loop:
19181       # if (curr < min) break
19182       39/compare %esi 1/r32/ecx
19183       0f 82/jump-if-addr< break/disp32
19184       # var v/ebx: (addr var) = lookup(*curr)
19185       (lookup *esi *(esi+4))  # => eax
19186       89/<- %ebx 0/r32/eax
19187       # if v is in a register
19188       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
19189       {
19190         0f 84/jump-if-= break/disp32
19191         {
19192 $emit-cleanup-code-for-non-outputs:check-for-previous-spill:
19193           8b/-> *(esi+8) 0/r32/eax  # Live-var-register-spilled
19194           3d/compare-eax-and 0/imm32/false
19195           0f 84/jump-if-= break/disp32
19196 $emit-cleanup-code-for-non-outputs:reclaim-var-in-register:
19197           # var reg/edi: (addr array name) = v->register
19198           (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
19199           89/<- %edi 0/r32/eax
19200           # if reg is not in function outputs, emit a pop
19201           (reg-in-function-outputs? *(ebp+0x10) %edi)  # => eax
19202           3d/compare-eax-and 0/imm32/false
19203           {
19204             75/jump-if-!= break/disp8
19205             (emit-pop-register *(ebp+8) %edi)
19206             eb/jump $emit-cleanup-code-for-non-outputs:reclaim-var-in-register-done/disp8
19207           }
19208           # otherwise just drop it from the stack
19209           (emit-indent *(ebp+8) *Curr-block-depth)
19210           (write-buffered *(ebp+8) "81 0/subop/add %esp 4/imm32\n")
19211         }
19212 $emit-cleanup-code-for-non-outputs:reclaim-var-in-register-done:
19213         eb/jump $emit-cleanup-code-for-non-outputs:continue/disp8
19214       }
19215       # otherwise v is on the stack
19216       {
19217         75/jump-if-!= break/disp8
19218 $emit-cleanup-code-for-non-outputs:var-on-stack:
19219         (size-of %ebx)  # => eax
19220         # don't emit code for labels
19221         3d/compare-eax-and 0/imm32
19222         74/jump-if-= break/disp8
19223 $emit-cleanup-code-for-non-outputs:reclaim-var-on-stack:
19224         (emit-indent *(ebp+8) *Curr-block-depth)
19225         (write-buffered *(ebp+8) "81 0/subop/add %esp ")
19226         (write-int32-hex-buffered *(ebp+8) %eax)
19227         (write-buffered *(ebp+8) "/imm32\n")
19228       }
19229 $emit-cleanup-code-for-non-outputs:continue:
19230       # curr -= 12
19231       81 5/subop/subtract %esi 0xc/imm32
19232       e9/jump loop/disp32
19233     }
19234 $emit-cleanup-code-for-non-outputs:end:
19235     # . restore registers
19236     5f/pop-to-edi
19237     5e/pop-to-esi
19238     5b/pop-to-ebx
19239     5a/pop-to-edx
19240     59/pop-to-ecx
19241     58/pop-to-eax
19242     # . epilogue
19243     89/<- %esp 5/r32/ebp
19244     5d/pop-to-ebp
19245     c3/return
19246 
19247 emit-push-register:  # out: (addr buffered-file), reg: (addr array byte)
19248     # . prologue
19249     55/push-ebp
19250     89/<- %ebp 4/r32/esp
19251     # eax = reg
19252     8b/-> *(ebp+0xc) 0/r32/eax
19253     # var prefix/eax: byte = reg->data[0]
19254     8a/copy-byte *(eax+4) 0/r32/AL
19255     81 4/subop/and %eax 0xff/imm32
19256     # if (prefix == 'x') push xmm register
19257     {
19258       3d/compare-eax-and 0x78/imm32/x
19259       0f 85/jump-if-!= break/disp32
19260       # TODO validate register
19261       (emit-indent *(ebp+8) *Curr-block-depth)
19262       (write-buffered *(ebp+8) "81 5/subop/subtract %esp 4/imm32\n")
19263       (emit-indent *(ebp+8) *Curr-block-depth)
19264       (write-buffered *(ebp+8) "f3 0f 11/<- *esp ")
19265       # var prefix/eax: byte = reg->data[3]
19266       8b/-> *(ebp+0xc) 0/r32/eax
19267       8a/copy-byte *(eax+7) 0/r32/AL
19268       81 4/subop/and %eax 0xff/imm32
19269       (write-byte-buffered *(ebp+8) %eax)
19270       (write-buffered *(ebp+8) "/x32\n")
19271       e9/jump $emit-push-register:end/disp32
19272     }
19273     # otherwise push gp register
19274     (emit-indent *(ebp+8) *Curr-block-depth)
19275     (write-buffered *(ebp+8) "ff 6/subop/push %")
19276     (write-buffered *(ebp+8) *(ebp+0xc))
19277     (write-buffered *(ebp+8) Newline)
19278 $emit-push-register:end:
19279     # . epilogue
19280     89/<- %esp 5/r32/ebp
19281     5d/pop-to-ebp
19282     c3/return
19283 
19284 emit-pop-register:  # out: (addr buffered-file), reg: (addr array byte)
19285     # . prologue
19286     55/push-ebp
19287     89/<- %ebp 4/r32/esp
19288     # . save registers
19289     50/push-eax
19290     # eax = reg
19291     8b/-> *(ebp+0xc) 0/r32/eax
19292     # var prefix/eax: byte = reg->data[0]
19293     8a/copy-byte *(eax+4) 0/r32/AL
19294     81 4/subop/and %eax 0xff/imm32
19295     # if (prefix == 'x') pop to xmm register
19296     {
19297       3d/compare-eax-and 0x78/imm32/x
19298       0f 85/jump-if-!= break/disp32
19299       # TODO validate register
19300       (emit-indent *(ebp+8) *Curr-block-depth)
19301       (write-buffered *(ebp+8) "f3 0f 10/-> *esp ")
19302       # var prefix/eax: byte = reg->data[3]
19303       8b/-> *(ebp+0xc) 0/r32/eax
19304       8a/copy-byte *(eax+7) 0/r32/AL
19305       81 4/subop/and %eax 0xff/imm32
19306       (write-byte-buffered *(ebp+8) %eax)
19307       (write-buffered *(ebp+8) "/x32\n")
19308       (emit-indent *(ebp+8) *Curr-block-depth)
19309       (write-buffered *(ebp+8) "81 0/subop/add %esp 4/imm32\n")
19310       e9/jump $emit-pop-register:end/disp32
19311     }
19312     # otherwise pop to gp register
19313     (emit-indent *(ebp+8) *Curr-block-depth)
19314     (write-buffered *(ebp+8) "8f 0/subop/pop %")
19315     (write-buffered *(ebp+8) *(ebp+0xc))
19316     (write-buffered *(ebp+8) Newline)
19317 $emit-pop-register:end:
19318     # . restore registers
19319     58/pop-to-eax
19320     # . epilogue
19321     89/<- %esp 5/r32/ebp
19322     5d/pop-to-ebp
19323     c3/return
19324 
19325 # emit clean-up code for 'vars' until a given label is encountered
19326 # doesn't actually modify 'vars' so we need traverse manually inside the stack
19327 emit-cleanup-code-until-target:  # out: (addr buffered-file), vars: (addr stack live-var), until-block-label: (addr array byte)
19328     # . prologue
19329     55/push-ebp
19330     89/<- %ebp 4/r32/esp
19331     # . save registers
19332     50/push-eax
19333     51/push-ecx
19334     52/push-edx
19335     53/push-ebx
19336     # ecx = vars
19337     8b/-> *(ebp+0xc) 1/r32/ecx
19338     # var eax: int = vars->top
19339     8b/-> *ecx 0/r32/eax
19340     # var curr/edx: (addr handle var) = &vars->data[vars->top - 12]
19341     8d/copy-address *(ecx+eax-4) 2/r32/edx  # vars + 8 + vars->top - 12/Live-var-size
19342     # var min/ecx: (addr handle var) = vars->data
19343     81 0/subop/add %ecx 8/imm32
19344     {
19345 $emit-cleanup-code-until-target:loop:
19346       # if (curr < min) break
19347       39/compare %edx 1/r32/ecx
19348       0f 82/jump-if-addr< break/disp32
19349       # var v/ebx: (handle var) = lookup(*curr)
19350       (lookup *edx *(edx+4))  # => eax
19351       89/<- %ebx 0/r32/eax
19352       # if (v->name == until-block-label) break
19353       (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
19354       (string-equal? %eax *(ebp+0x10))  # => eax
19355       3d/compare-eax-and 0/imm32/false
19356       0f 85/jump-if-!= break/disp32
19357       # if v is in a register
19358       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
19359       {
19360         0f 84/jump-if-= break/disp32
19361         {
19362 $emit-cleanup-code-until-target:check-for-previous-spill:
19363           8b/-> *(edx+8) 0/r32/eax  # Live-var-register-spilled
19364           3d/compare-eax-and 0/imm32/false
19365           74/jump-if-= break/disp8
19366 $emit-cleanup-code-until-target:reclaim-var-in-register:
19367           (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
19368           (emit-pop-register *(ebp+8) %eax)
19369         }
19370         eb/jump $emit-cleanup-code-until-target:continue/disp8
19371       }
19372       # otherwise v is on the stack
19373       {
19374         75/jump-if-!= break/disp8
19375 $emit-cleanup-code-until-target:reclaim-var-on-stack:
19376         (size-of %ebx)  # => eax
19377         # don't emit code for labels
19378         3d/compare-eax-and 0/imm32
19379         74/jump-if-= break/disp8
19380         #
19381         (emit-indent *(ebp+8) *Curr-block-depth)
19382         (write-buffered *(ebp+8) "81 0/subop/add %esp ")
19383         (write-int32-hex-buffered *(ebp+8) %eax)
19384         (write-buffered *(ebp+8) "/imm32\n")
19385       }
19386 $emit-cleanup-code-until-target:continue:
19387       # curr -= 12
19388       81 5/subop/subtract %edx 0xc/imm32
19389       e9/jump loop/disp32
19390     }
19391 $emit-cleanup-code-until-target:end:
19392     # . restore registers
19393     5b/pop-to-ebx
19394     5a/pop-to-edx
19395     59/pop-to-ecx
19396     58/pop-to-eax
19397     # . epilogue
19398     89/<- %esp 5/r32/ebp
19399     5d/pop-to-ebp
19400     c3/return
19401 
19402 # update Curr-local-stack-offset assuming vars until some block depth are popped
19403 # doesn't actually modify 'vars', so we need traverse manually inside the stack
19404 clean-up-stack-offset-state:  # vars: (addr stack live-var), until-block-depth: int
19405     # . prologue
19406     55/push-ebp
19407     89/<- %ebp 4/r32/esp
19408     # . save registers
19409     50/push-eax
19410     51/push-ecx
19411     52/push-edx
19412     53/push-ebx
19413     56/push-esi
19414     # ecx = vars
19415     8b/-> *(ebp+8) 1/r32/ecx
19416     # var esi: int = vars->top
19417     8b/-> *ecx 6/r32/esi
19418     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
19419     8d/copy-address *(ecx+esi-4) 6/r32/esi  # vars + 8 + vars->top - 12/Live-var-size
19420     # var min/ecx: (addr handle var) = vars->data
19421     81 0/subop/add %ecx 8/imm32
19422     # edx = until-block-depth
19423     8b/-> *(ebp+0xc) 2/r32/edx
19424     {
19425 $clean-up-stack-offset-state:loop:
19426       # if (curr < min) break
19427       39/compare %esi 1/r32/ecx
19428       0f 82/jump-if-addr< break/disp32
19429       # var v/ebx: (addr var) = lookup(*curr)
19430       (lookup *esi *(esi+4))  # => eax
19431       89/<- %ebx 0/r32/eax
19432       # if (v->block-depth < until-block-depth) break
19433       39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
19434       0f 8c/jump-if-< break/disp32
19435       # if v is in a register
19436       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
19437       {
19438         0f 84/jump-if-= break/disp32
19439         {
19440 $clean-up-stack-offset-state:check-for-previous-spill:
19441           8b/-> *(esi+8) 0/r32/eax  # Live-var-register-spilled
19442           3d/compare-eax-and 0/imm32/false
19443           74/jump-if-= break/disp8
19444 $clean-up-stack-offset-state:reclaim-var-in-register:
19445           81 0/subop/add *Curr-local-stack-offset 4/imm32
19446         }
19447         eb/jump $clean-up-stack-offset-state:continue/disp8
19448       }
19449       # otherwise v is on the stack
19450       {
19451         75/jump-if-!= break/disp8
19452 $clean-up-stack-offset-state:var-on-stack:
19453         (size-of %ebx)  # => eax
19454         01/add-to *Curr-local-stack-offset 0/r32/eax
19455       }
19456 $clean-up-stack-offset-state:continue:
19457       # curr -= 12
19458       81 5/subop/subtract %esi 0xc/imm32
19459       e9/jump loop/disp32
19460     }
19461 $clean-up-stack-offset-state:end:
19462     # . restore registers
19463     5e/pop-to-esi
19464     5b/pop-to-ebx
19465     5a/pop-to-edx
19466     59/pop-to-ecx
19467     58/pop-to-eax
19468     # . epilogue
19469     89/<- %esp 5/r32/ebp
19470     5d/pop-to-ebp
19471     c3/return
19472 
19473 # Return true if there isn't a variable in 'vars' with the same block-depth
19474 # and register as 'v'.
19475 # 'v' is guaranteed not to be within 'vars'.
19476 not-yet-spilled-this-block?:  # v: (addr var), vars: (addr stack live-var) -> result/eax: boolean
19477     # . prologue
19478     55/push-ebp
19479     89/<- %ebp 4/r32/esp
19480     # . save registers
19481     51/push-ecx
19482     52/push-edx
19483     53/push-ebx
19484     56/push-esi
19485     57/push-edi
19486     # ecx = vars
19487     8b/-> *(ebp+0xc) 1/r32/ecx
19488     # var eax: int = vars->top
19489     8b/-> *ecx 0/r32/eax
19490     # var curr/edx: (addr handle var) = &vars->data[vars->top - 12]
19491     8d/copy-address *(ecx+eax-4) 2/r32/edx  # vars + 8 + vars->top - 12/Live-var-size
19492     # var min/ecx: (addr handle var) = vars->data
19493     8d/copy-address *(ecx+8) 1/r32/ecx
19494     # var depth/ebx: int = v->block-depth
19495     8b/-> *(ebp+8) 3/r32/ebx
19496     8b/-> *(ebx+0x10) 3/r32/ebx  # Var-block-depth
19497     # var needle/esi: (addr array byte) = v->register
19498     8b/-> *(ebp+8) 6/r32/esi
19499     (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
19500     89/<- %esi 0/r32/eax
19501     {
19502 $not-yet-spilled-this-block?:loop:
19503       # if (curr < min) break
19504       39/compare %edx 1/r32/ecx
19505       0f 82/jump-if-addr< break/disp32
19506       # var cand/edi: (addr var) = lookup(*curr)
19507       (lookup *edx *(edx+4))  # => eax
19508       89/<- %edi 0/r32/eax
19509       # if (cand->block-depth < depth) break
19510       39/compare *(edi+0x10) 3/r32/ebx  # Var-block-depth
19511       0f 8c/jump-if-< break/disp32
19512       # var cand-reg/edi: (array array byte) = cand->reg
19513       (lookup *(edi+0x18) *(edi+0x1c))  # Var-register Var-register => eax
19514       89/<- %edi 0/r32/eax
19515       # if (cand-reg == null) continue
19516       {
19517 $not-yet-spilled-this-block?:check-reg:
19518         81 7/subop/compare %edi 0/imm32
19519         0f 84/jump-if-= break/disp32
19520         # if (cand-reg == needle) return true
19521         (string-equal? %esi %edi)  # => eax
19522         3d/compare-eax-and 0/imm32/false
19523         74/jump-if-= break/disp8
19524 $not-yet-spilled-this-block?:return-false:
19525         b8/copy-to-eax 0/imm32/false
19526         eb/jump $not-yet-spilled-this-block?:end/disp8
19527       }
19528 $not-yet-spilled-this-block?:continue:
19529       # curr -= 12
19530       81 5/subop/subtract %edx 0xc/imm32
19531       e9/jump loop/disp32
19532     }
19533 $not-yet-spilled-this-block?:return-true:
19534     # return true
19535     b8/copy-to-eax 1/imm32/true
19536 $not-yet-spilled-this-block?:end:
19537     # . restore registers
19538     5f/pop-to-edi
19539     5e/pop-to-esi
19540     5b/pop-to-ebx
19541     5a/pop-to-edx
19542     59/pop-to-ecx
19543     # . epilogue
19544     89/<- %esp 5/r32/ebp
19545     5d/pop-to-ebp
19546     c3/return
19547 
19548 # could the register of 'v' ever be written to by one of the vars in fn-outputs?
19549 will-not-write-some-register?:  # v: (addr var), stmts: (addr list stmt), fn: (addr function) -> result/eax: boolean
19550     # . prologue
19551     55/push-ebp
19552     89/<- %ebp 4/r32/esp
19553     # eax = v
19554     8b/-> *(ebp+8) 0/r32/eax
19555     # var reg/eax: (addr array byte) = lookup(v->register)
19556     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
19557     # var target/eax: (addr var) = find-register(fn-outputs, reg)
19558     (find-register *(ebp+0x10) %eax)  # => eax
19559     # if (target == 0) return true
19560     {
19561       3d/compare-eax-and 0/imm32
19562       75/jump-if-!= break/disp8
19563       b8/copy-to-eax 1/imm32/true
19564       eb/jump $will-not-write-some-register?:end/disp8
19565     }
19566     # return !assigns-in-stmts?(stmts, target)
19567     (assigns-in-stmts? *(ebp+0xc) %eax)  # => eax
19568     3d/compare-eax-and 0/imm32/false
19569     # assume: true = 1, so no need to mask with 0x000000ff
19570     0f 94/set-if-= %al
19571 $will-not-write-some-register?:end:
19572     # . epilogue
19573     89/<- %esp 5/r32/ebp
19574     5d/pop-to-ebp
19575     c3/return
19576 
19577 # return fn output with matching register
19578 # always returns false if 'reg' is null
19579 find-register:  # fn: (addr function), reg: (addr array byte) -> result/eax: (addr var)
19580     # . prologue
19581     55/push-ebp
19582     89/<- %ebp 4/r32/esp
19583     # . save registers
19584     51/push-ecx
19585     # var curr/ecx: (addr list var) = lookup(fn->outputs)
19586     8b/-> *(ebp+8) 1/r32/ecx
19587     (lookup *(ecx+0x10) *(ecx+0x14))  # Function-outputs Function-outputs => eax
19588     89/<- %ecx 0/r32/eax
19589     {
19590 $find-register:loop:
19591       # if (curr == 0) break
19592       81 7/subop/compare %ecx 0/imm32
19593       74/jump-if-= break/disp8
19594       # eax = curr->value->register
19595       (lookup *ecx *(ecx+4))  # List-value List-value => eax
19596       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
19597       # if (eax == reg) return curr->value
19598 $find-register:compare:
19599       (string-equal? *(ebp+0xc) %eax)  # => eax
19600       {
19601         3d/compare-eax-and 0/imm32/false
19602         74/jump-if-= break/disp8
19603 $find-register:found:
19604         (lookup *ecx *(ecx+4))  # List-value List-value => eax
19605         eb/jump $find-register:end/disp8
19606       }
19607       # curr = lookup(curr->next)
19608       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
19609       89/<- %ecx 0/r32/eax
19610       #
19611       eb/jump loop/disp8
19612     }
19613 $find-register:end:
19614     # . restore registers
19615     59/pop-to-ecx
19616     # . epilogue
19617     89/<- %esp 5/r32/ebp
19618     5d/pop-to-ebp
19619     c3/return
19620 
19621 assigns-in-stmts?:  # stmts: (addr list stmt), v: (addr var) -> result/eax: boolean
19622     # . prologue
19623     55/push-ebp
19624     89/<- %ebp 4/r32/esp
19625     # . save registers
19626     51/push-ecx
19627     # var curr/ecx: (addr list stmt) = stmts
19628     8b/-> *(ebp+8) 1/r32/ecx
19629     {
19630       # if (curr == 0) break
19631       81 7/subop/compare %ecx 0/imm32
19632       74/jump-if-= break/disp8
19633       # if assigns-in-stmt?(curr->value, v) return true
19634       (lookup *ecx *(ecx+4))  # List-value List-value => eax
19635       (assigns-in-stmt? %eax *(ebp+0xc))  # => eax
19636       3d/compare-eax-and 0/imm32/false
19637       75/jump-if-!= break/disp8
19638       # curr = lookup(curr->next)
19639       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
19640       89/<- %ecx 0/r32/eax
19641       #
19642       eb/jump loop/disp8
19643     }
19644 $assigns-in-stmts?:end:
19645     # . restore registers
19646     59/pop-to-ecx
19647     # . epilogue
19648     89/<- %esp 5/r32/ebp
19649     5d/pop-to-ebp
19650     c3/return
19651 
19652 assigns-in-stmt?:  # stmt: (addr stmt), v: (addr var) -> result/eax: boolean
19653     # . prologue
19654     55/push-ebp
19655     89/<- %ebp 4/r32/esp
19656     # . save registers
19657     51/push-ecx
19658     # ecx = stmt
19659     8b/-> *(ebp+8) 1/r32/ecx
19660     # if stmt is a stmt1, return assigns-in-stmt-vars?(stmt->outputs, v)
19661     {
19662       81 7/subop/compare *ecx 1/imm32/stmt1  # Stmt-tag
19663       75/jump-if-!= break/disp8
19664       (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
19665       (assigns-in-stmt-vars? %eax *(ebp+0xc))  # => eax
19666       eb/jump $assigns-in-stmt?:end/disp8
19667     }
19668     # if stmt is a block, return assigns-in-stmts?(stmt->stmts, v)
19669     {
19670       81 7/subop/compare *ecx 0/imm32/block  # Stmt-tag
19671       75/jump-if-!= break/disp8
19672       (lookup *(ecx+4) *(ecx+8))  # Block-stmts Block-stmts => eax
19673       (assigns-in-stmts? %eax *(ebp+0xc))  # => eax
19674       eb/jump $assigns-in-stmt?:end/disp8
19675     }
19676     # otherwise return false
19677     b8/copy 0/imm32/false
19678 $assigns-in-stmt?:end:
19679     # . restore registers
19680     59/pop-to-ecx
19681     # . epilogue
19682     89/<- %esp 5/r32/ebp
19683     5d/pop-to-ebp
19684     c3/return
19685 
19686 assigns-in-stmt-vars?:  # stmt-var: (addr stmt-var), v: (addr var) -> result/eax: boolean
19687     # . prologue
19688     55/push-ebp
19689     89/<- %ebp 4/r32/esp
19690     # . save registers
19691     51/push-ecx
19692     # var curr/ecx: (addr stmt-var) = stmt-var
19693     8b/-> *(ebp+8) 1/r32/ecx
19694     {
19695       # if (curr == 0) break
19696       81 7/subop/compare %ecx 0/imm32
19697       74/jump-if-= break/disp8
19698       # eax = lookup(curr->value)
19699       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
19700       # if (eax == v  &&  curr->is-deref? == false) return true
19701       {
19702         39/compare *(ebp+0xc) 0/r32/eax
19703         75/jump-if-!= break/disp8
19704         81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
19705         75/jump-if-!= break/disp8
19706         b8/copy-to-eax 1/imm32/true
19707         eb/jump $assigns-in-stmt-vars?:end/disp8
19708       }
19709       # curr = lookup(curr->next)
19710       (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
19711       89/<- %ecx 0/r32/eax
19712       #
19713       eb/jump loop/disp8
19714     }
19715 $assigns-in-stmt-vars?:end:
19716     # . restore registers
19717     59/pop-to-ecx
19718     # . epilogue
19719     89/<- %esp 5/r32/ebp
19720     5d/pop-to-ebp
19721     c3/return
19722 
19723 # is there a var before 'v' with the same block-depth and register on the 'vars' stack?
19724 # v is guaranteed to be within vars
19725 # 'start' is provided as an optimization, a pointer within vars
19726 # *start == v
19727 same-register-spilled-before?:  # v: (addr var), vars: (addr stack (handle var)), start: (addr var) -> result/eax: boolean
19728     # . prologue
19729     55/push-ebp
19730     89/<- %ebp 4/r32/esp
19731     # . save registers
19732     51/push-ecx
19733     52/push-edx
19734     53/push-ebx
19735     56/push-esi
19736     57/push-edi
19737     # ecx = v
19738     8b/-> *(ebp+8) 1/r32/ecx
19739     # var reg/edx: (addr array byte) = lookup(v->register)
19740     (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
19741     89/<- %edx 0/r32/eax
19742     # var depth/ebx: int = v->block-depth
19743     8b/-> *(ecx+0x10) 3/r32/ebx  # Var-block-depth
19744     # var min/ecx: (addr handle var) = vars->data
19745     8b/-> *(ebp+0xc) 1/r32/ecx
19746     81 0/subop/add %ecx 8/imm32
19747     # TODO: check that start >= min and start < &vars->data[top]
19748     # TODO: check that *start == v
19749     # var curr/esi: (addr handle var) = start
19750     8b/-> *(ebp+0x10) 6/r32/esi
19751     # curr -= 8
19752     81 5/subop/subtract %esi 8/imm32
19753     {
19754 $same-register-spilled-before?:loop:
19755       # if (curr < min) break
19756       39/compare %esi 1/r32/ecx
19757       0f 82/jump-if-addr< break/disp32
19758       # var x/eax: (addr var) = lookup(*curr)
19759       (lookup *esi *(esi+4))  # => eax
19760       # if (x->block-depth < depth) break
19761       39/compare *(eax+0x10) 3/r32/ebx  # Var-block-depth
19762       0f 8c/jump-if-< break/disp32
19763       # if (x->register == 0) continue
19764       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
19765       74/jump-if-= $same-register-spilled-before?:continue/disp8
19766       # if (x->register == reg) return true
19767       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
19768       (string-equal? %eax %edx)  # => eax
19769       3d/compare-eax-and 0/imm32/false
19770       b8/copy-to-eax 1/imm32/true
19771       75/jump-if-!= $same-register-spilled-before?:end/disp8
19772 $same-register-spilled-before?:continue:
19773       # curr -= 8
19774       81 5/subop/subtract %esi 8/imm32
19775       e9/jump loop/disp32
19776     }
19777 $same-register-spilled-before?:false:
19778     b8/copy-to-eax 0/imm32/false
19779 $same-register-spilled-before?:end:
19780     # . restore registers
19781     5f/pop-to-edi
19782     5e/pop-to-esi
19783     5b/pop-to-ebx
19784     5a/pop-to-edx
19785     59/pop-to-ecx
19786     # . epilogue
19787     89/<- %esp 5/r32/ebp
19788     5d/pop-to-ebp
19789     c3/return
19790 
19791 # clean up global state for 'vars' until some block depth (inclusive)
19792 clean-up-blocks:  # vars: (addr stack live-var), until-block-depth: int, fn: (addr function)
19793     # . prologue
19794     55/push-ebp
19795     89/<- %ebp 4/r32/esp
19796     # . save registers
19797     50/push-eax
19798     51/push-ecx
19799     56/push-esi
19800     # esi = vars
19801     8b/-> *(ebp+8) 6/r32/esi
19802     # ecx = until-block-depth
19803     8b/-> *(ebp+0xc) 1/r32/ecx
19804     {
19805 $clean-up-blocks:reclaim-loop:
19806       # if (vars->top <= 0) break
19807       8b/-> *esi 0/r32/eax  # Stack-top
19808       3d/compare-eax-and 0/imm32
19809       0f 8e/jump-if-<= break/disp32
19810       # var v/eax: (addr var) = lookup(vars[vars->top-12])
19811       (lookup *(esi+eax-4) *(esi+eax))  # vars + 8 + vars->top - 12 => eax
19812       # if (v->block-depth < until-block-depth) break
19813       39/compare *(eax+0x10) 1/r32/ecx  # Var-block-depth
19814       0f 8c/jump-if-< break/disp32
19815       (pop %esi)  # => eax
19816       (pop %esi)  # => eax
19817       (pop %esi)  # => eax
19818       e9/jump loop/disp32
19819     }
19820 $clean-up-blocks:end:
19821     # . restore registers
19822     5e/pop-to-esi
19823     59/pop-to-ecx
19824     58/pop-to-eax
19825     # . epilogue
19826     89/<- %esp 5/r32/ebp
19827     5d/pop-to-ebp
19828     c3/return
19829 
19830 reg-in-function-outputs?:  # fn: (addr function), target: (addr array byte) -> result/eax: boolean
19831     # . prologue
19832     55/push-ebp
19833     89/<- %ebp 4/r32/esp
19834     # . save registers
19835     51/push-ecx
19836     # var curr/ecx: (addr list var) = lookup(fn->outputs)
19837     8b/-> *(ebp+8) 1/r32/ecx
19838     (lookup *(ecx+0x10) *(ecx+0x14))  # Function-outputs Function-outputs => eax
19839     89/<- %ecx 0/r32/eax
19840     # while curr != null
19841     {
19842       81 7/subop/compare %ecx 0/imm32
19843       74/jump-if-= break/disp8
19844       # var v/eax: (addr var) = lookup(curr->value)
19845       (lookup *ecx *(ecx+4))  # List-value List-value => eax
19846       # var reg/eax: (addr array byte) = lookup(v->register)
19847       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
19848       # if (reg == target) return true
19849       (string-equal? %eax *(ebp+0xc))  # => eax
19850       3d/compare-eax-and 0/imm32/false
19851       75/jump-if-!= $reg-in-function-outputs?:end/disp8
19852       # curr = curr->next
19853       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
19854       89/<- %ecx 0/r32/eax
19855       #
19856       eb/jump loop/disp8
19857     }
19858     # return false
19859     b8/copy-to-eax 0/imm32
19860 $reg-in-function-outputs?:end:
19861     # . restore registers
19862     59/pop-to-ecx
19863     # . epilogue
19864     89/<- %esp 5/r32/ebp
19865     5d/pop-to-ebp
19866     c3/return
19867 
19868 emit-subx-var-def:  # out: (addr buffered-file), stmt: (addr stmt)
19869     # . prologue
19870     55/push-ebp
19871     89/<- %ebp 4/r32/esp
19872     # . save registers
19873     50/push-eax
19874     51/push-ecx
19875     52/push-edx
19876     # eax = stmt
19877     8b/-> *(ebp+0xc) 0/r32/eax
19878     # var v/ecx: (addr var)
19879     (lookup *(eax+4) *(eax+8))  # Vardef-var Vardef-var => eax
19880     89/<- %ecx 0/r32/eax
19881     # v->block-depth = *Curr-block-depth
19882     8b/-> *Curr-block-depth 0/r32/eax
19883     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
19884     # var n/edx: int = size-of(stmt->var)
19885     (size-of %ecx)  # => eax
19886     89/<- %edx 0/r32/eax
19887     # *Curr-local-stack-offset -= n
19888     29/subtract-from *Curr-local-stack-offset 2/r32/edx
19889     # v->offset = *Curr-local-stack-offset
19890     8b/-> *Curr-local-stack-offset 0/r32/eax
19891     89/<- *(ecx+0x14) 0/r32/eax  # Var-offset
19892     # if v is an array, do something special to initialize it
19893     {
19894       (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
19895       (is-mu-array? %eax)  # => eax
19896       3d/compare-eax-and 0/imm32/false
19897       0f 84/jump-if-= break/disp32
19898       # var array-size-without-size/edx: int = n-4
19899       81 5/subop/subtract %edx 4/imm32
19900       #
19901       (emit-array-data-initialization *(ebp+8) %edx)
19902       e9/jump $emit-subx-var-def:end/disp32
19903     }
19904     # another special-case for initializing streams
19905     # a stream is an array with 2 extra pointers
19906     {
19907       (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
19908       (is-mu-stream? %eax)  # => eax
19909       3d/compare-eax-and 0/imm32/false
19910       0f 84/jump-if-= break/disp32
19911       # var array-size-without-size/edx: int = n-12
19912       81 5/subop/subtract %edx 0xc/imm32
19913       (emit-array-data-initialization *(ebp+8) %edx)
19914       # emit read and write pointers
19915       (emit-indent *(ebp+8) *Curr-block-depth)
19916       (write-buffered *(ebp+8) "68/push 0/imm32\n")
19917       (emit-indent *(ebp+8) *Curr-block-depth)
19918       (write-buffered *(ebp+8) "68/push 0/imm32\n")
19919       #
19920       eb/jump $emit-subx-var-def:end/disp8
19921     }
19922     # while n > 0
19923     {
19924       81 7/subop/compare %edx 0/imm32
19925       7e/jump-if-<= break/disp8
19926       (emit-indent *(ebp+8) *Curr-block-depth)
19927       (write-buffered *(ebp+8) "68/push 0/imm32\n")
19928       # n -= 4
19929       81 5/subop/subtract %edx 4/imm32
19930       #
19931       eb/jump loop/disp8
19932     }
19933 $emit-subx-var-def:end:
19934     # . restore registers
19935     5a/pop-to-edx
19936     59/pop-to-ecx
19937     58/pop-to-eax
19938     # . epilogue
19939     89/<- %esp 5/r32/ebp
19940     5d/pop-to-ebp
19941     c3/return
19942 
19943 emit-array-data-initialization:  # out: (addr buffered-file), n: int
19944     # . prologue
19945     55/push-ebp
19946     89/<- %ebp 4/r32/esp
19947     #
19948     (emit-indent *(ebp+8) *Curr-block-depth)
19949     (write-buffered *(ebp+8) "(push-n-zero-bytes ")
19950     (write-int32-hex-buffered *(ebp+8) *(ebp+0xc))
19951     (write-buffered *(ebp+8) ")\n")
19952     (emit-indent *(ebp+8) *Curr-block-depth)
19953     (write-buffered *(ebp+8) "68/push ")
19954     (write-int32-hex-buffered *(ebp+8) *(ebp+0xc))
19955     (write-buffered *(ebp+8) "/imm32\n")
19956 $emit-array-data-initialization:end:
19957     # . epilogue
19958     89/<- %esp 5/r32/ebp
19959     5d/pop-to-ebp
19960     c3/return
19961 
19962 emit-subx-stmt:  # out: (addr buffered-file), stmt: (addr stmt), primitives: (addr primitive), err: (addr buffered-file), ed: (addr exit-descriptor)
19963     # . prologue
19964     55/push-ebp
19965     89/<- %ebp 4/r32/esp
19966     # . save registers
19967     50/push-eax
19968     51/push-ecx
19969     # - some special-case primitives that don't actually use the 'primitives' data structure
19970     # var op/ecx: (addr array byte) = lookup(stmt->operation)
19971     8b/-> *(ebp+0xc) 1/r32/ecx
19972     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
19973     89/<- %ecx 0/r32/eax
19974     # array size
19975     {
19976       # if (!string-equal?(stmt->operation, "length")) break
19977       (string-equal? %ecx "length")  # => eax
19978       3d/compare-eax-and 0/imm32
19979       0f 84/jump-if-= break/disp32
19980       (translate-mu-length-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
19981       e9/jump $emit-subx-stmt:end/disp32
19982     }
19983     # index into array
19984     {
19985       # if (!string-equal?(stmt->operation, "index")) break
19986       (string-equal? %ecx "index")  # => eax
19987       3d/compare-eax-and 0/imm32
19988       0f 84/jump-if-= break/disp32
19989       (translate-mu-index-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
19990       e9/jump $emit-subx-stmt:end/disp32
19991     }
19992     # compute-offset for index into array
19993     {
19994       # if (!string-equal?(stmt->operation, "compute-offset")) break
19995       (string-equal? %ecx "compute-offset")  # => eax
19996       3d/compare-eax-and 0/imm32
19997       0f 84/jump-if-= break/disp32
19998       (translate-mu-compute-index-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
19999       e9/jump $emit-subx-stmt:end/disp32
20000     }
20001     # get field from record
20002     {
20003       # if (!string-equal?(stmt->operation, "get")) break
20004       (string-equal? %ecx "get")  # => eax
20005       3d/compare-eax-and 0/imm32
20006       0f 84/jump-if-= break/disp32
20007       (translate-mu-get-stmt *(ebp+8) *(ebp+0xc))
20008       e9/jump $emit-subx-stmt:end/disp32
20009     }
20010     # allocate scalar
20011     {
20012       # if (!string-equal?(stmt->operation, "allocate")) break
20013       (string-equal? %ecx "allocate")  # => eax
20014       3d/compare-eax-and 0/imm32
20015       0f 84/jump-if-= break/disp32
20016       (translate-mu-allocate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
20017       e9/jump $emit-subx-stmt:end/disp32
20018     }
20019     # copy-object
20020     {
20021       # if (!string-equal?(stmt->operation, "copy-object")) break
20022       (string-equal? %ecx "copy-object")  # => eax
20023       3d/compare-eax-and 0/imm32
20024       0f 84/jump-if-= break/disp32
20025       (translate-mu-copy-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
20026       e9/jump $emit-subx-stmt:end/disp32
20027     }
20028     # allocate array
20029     {
20030       # if (!string-equal?(stmt->operation, "populate")) break
20031       (string-equal? %ecx "populate")  # => eax
20032       3d/compare-eax-and 0/imm32
20033       0f 84/jump-if-= break/disp32
20034       (translate-mu-populate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
20035       e9/jump $emit-subx-stmt:end/disp32
20036     }
20037     # allocate stream
20038     {
20039       # if (!string-equal?(stmt->operation, "populate-stream")) break
20040       (string-equal? %ecx "populate-stream")  # => eax
20041       3d/compare-eax-and 0/imm32
20042       0f 84/jump-if-= break/disp32
20043       (translate-mu-populate-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
20044       e9/jump $emit-subx-stmt:end/disp32
20045     }
20046     # read from stream
20047     {
20048       # if (!string-equal?(stmt->operation, "read-from-stream")) break
20049       (string-equal? %ecx "read-from-stream")  # => eax
20050       3d/compare-eax-and 0/imm32
20051       0f 84/jump-if-= break/disp32
20052       (translate-mu-read-from-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
20053       e9/jump $emit-subx-stmt:end/disp32
20054     }
20055     # write to stream
20056     {
20057       # if (!string-equal?(stmt->operation, "write-to-stream")) break
20058       (string-equal? %ecx "write-to-stream")  # => eax
20059       3d/compare-eax-and 0/imm32
20060       0f 84/jump-if-= break/disp32
20061       (translate-mu-write-to-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
20062       e9/jump $emit-subx-stmt:end/disp32
20063     }
20064     # - if stmt matches a primitive, emit it
20065     {
20066 $emit-subx-stmt:check-for-primitive:
20067       # var curr/eax: (addr primitive)
20068       (find-matching-primitive *(ebp+0x10) *(ebp+0xc))  # primitives, stmt => eax
20069       3d/compare-eax-and 0/imm32
20070       74/jump-if-= break/disp8
20071 $emit-subx-stmt:primitive:
20072       (emit-subx-primitive *(ebp+8) *(ebp+0xc) %eax)  # out, stmt, curr
20073       e9/jump $emit-subx-stmt:end/disp32
20074     }
20075     # - otherwise emit a call
20076     # TODO: type-checking
20077 $emit-subx-stmt:call:
20078     (emit-call *(ebp+8) *(ebp+0xc))
20079 $emit-subx-stmt:end:
20080     # . restore registers
20081     59/pop-to-ecx
20082     58/pop-to-eax
20083     # . epilogue
20084     89/<- %esp 5/r32/ebp
20085     5d/pop-to-ebp
20086     c3/return
20087 
20088 translate-mu-length-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
20089     # . prologue
20090     55/push-ebp
20091     89/<- %ebp 4/r32/esp
20092     # . save registers
20093     50/push-eax
20094     51/push-ecx
20095     52/push-edx
20096     53/push-ebx
20097     56/push-esi
20098     # esi = stmt
20099     8b/-> *(ebp+0xc) 6/r32/esi
20100     # var base/ebx: (addr var) = stmt->inouts[0]->value
20101     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
20102     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
20103     89/<- %ebx 0/r32/eax
20104     # var elemsize/ecx: int = array-element-size(base)
20105     (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
20106     89/<- %ecx 0/r32/eax
20107     # var outreg/edx: (addr array byte) = stmt->outputs[0]->value->register
20108     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
20109     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
20110     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
20111     89/<- %edx 0/r32/eax
20112     # if elemsize == 1
20113     {
20114       81 7/subop/compare %ecx 1/imm32
20115       75/jump-if-!= break/disp8
20116 $translate-mu-length-stmt:size-1:
20117       (emit-save-size-to *(ebp+8) %ebx %edx)
20118       e9/jump $translate-mu-length-stmt:end/disp32
20119     }
20120     # if elemsize is a power of 2 less than 256
20121     {
20122       (power-of-2? %ecx *(ebp+0x10) *(ebp+0x14))  # => eax
20123       3d/compare-eax-and 0/imm32/false
20124       74/jump-if-= break/disp8
20125       81 7/subop/compare %ecx 0xff/imm32
20126       7f/jump-if-> break/disp8
20127 $translate-mu-length-stmt:size-power-of-2:
20128       (emit-save-size-to *(ebp+8) %ebx %edx)
20129       (emit-divide-by-shift-right *(ebp+8) %edx %ecx)
20130       e9/jump $translate-mu-length-stmt:end/disp32
20131     }
20132     # otherwise, the complex case
20133     # . emit register spills
20134     {
20135 $translate-mu-length-stmt:complex:
20136       (string-equal? %edx "eax")  # => eax
20137       3d/compare-eax-and 0/imm32/false
20138       75/break-if-!= break/disp8
20139       (emit-indent *(ebp+8) *Curr-block-depth)
20140       (write-buffered *(ebp+8) "50/push-eax\n")
20141     }
20142     {
20143       (string-equal? %edx "ecx")  # => eax
20144       3d/compare-eax-and 0/imm32/false
20145       75/break-if-!= break/disp8
20146       (emit-indent *(ebp+8) *Curr-block-depth)
20147       (write-buffered *(ebp+8) "51/push-ecx\n")
20148     }
20149     {
20150       (string-equal? %edx "edx")  # => eax
20151       3d/compare-eax-and 0/imm32/false
20152       75/break-if-!= break/disp8
20153       (emit-indent *(ebp+8) *Curr-block-depth)
20154       (write-buffered *(ebp+8) "52/push-edx\n")
20155     }
20156     # .
20157     (emit-save-size-to *(ebp+8) %ebx "eax")
20158     (emit-indent *(ebp+8) *Curr-block-depth)
20159     (write-buffered *(ebp+8) "31/xor %edx 2/r32/edx\n")
20160     (emit-indent *(ebp+8) *Curr-block-depth)
20161     (write-buffered *(ebp+8) "b9/copy-to-ecx ")
20162     (write-int32-hex-buffered *(ebp+8) %ecx)
20163     (write-buffered *(ebp+8) "/imm32\n")
20164     (emit-indent *(ebp+8) *Curr-block-depth)
20165     (write-buffered *(ebp+8) "f7 7/subop/idiv-eax-edx-by %ecx\n")
20166     {
20167       (string-equal? %edx "eax")  # => eax
20168       3d/compare-eax-and 0/imm32/false
20169       75/break-if-!= break/disp8
20170       (emit-indent *(ebp+8) *Curr-block-depth)
20171       (write-buffered *(ebp+8) "89/<- %")
20172       (write-buffered *(ebp+8) %edx)
20173       (write-buffered *(ebp+8) " 0/r32/eax\n")
20174     }
20175     # . emit register restores
20176     {
20177       (string-equal? %edx "edx")  # => eax
20178       3d/compare-eax-and 0/imm32/false
20179       75/break-if-!= break/disp8
20180       (emit-indent *(ebp+8) *Curr-block-depth)
20181       (write-buffered *(ebp+8) "5a/pop-to-edx\n")
20182     }
20183     {
20184       (string-equal? %edx "ecx")  # => eax
20185       3d/compare-eax-and 0/imm32/false
20186       75/break-if-!= break/disp8
20187       (emit-indent *(ebp+8) *Curr-block-depth)
20188       (write-buffered *(ebp+8) "59/pop-to-ecx\n")
20189     }
20190     {
20191       (string-equal? %edx "eax")  # => eax
20192       3d/compare-eax-and 0/imm32/false
20193       75/break-if-!= break/disp8
20194       (emit-indent *(ebp+8) *Curr-block-depth)
20195       (write-buffered *(ebp+8) "58/pop-to-eax\n")
20196     }
20197 $translate-mu-length-stmt:end:
20198     # . restore registers
20199     5e/pop-to-esi
20200     5b/pop-to-ebx
20201     5a/pop-to-edx
20202     59/pop-to-ecx
20203     58/pop-to-eax
20204     # . epilogue
20205     89/<- %esp 5/r32/ebp
20206     5d/pop-to-ebp
20207     c3/return
20208 
20209 array-element-size:  # arr: (addr var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
20210     # . prologue
20211     55/push-ebp
20212     89/<- %ebp 4/r32/esp
20213     #
20214     (array-element-type-id *(ebp+8) *(ebp+0xc) *(ebp+0x10))  # => eax
20215     (size-of-type-id-as-array-element %eax)  # => eax
20216 $array-element-size:end:
20217     # . epilogue
20218     89/<- %esp 5/r32/ebp
20219     5d/pop-to-ebp
20220     c3/return
20221 
20222 array-element-type-id:  # v: (addr var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: type-id
20223     # precondition: n is positive
20224     # . prologue
20225     55/push-ebp
20226     89/<- %ebp 4/r32/esp
20227     #
20228     8b/-> *(ebp+8) 0/r32/eax
20229     # var t/eax: (addr type-tree)
20230     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20231     # if t == 0 abort
20232     3d/compare-eax-with 0/imm32
20233     0f 84/jump-if-== $array-element-type-id:error0/disp32
20234     # if t->is-atom? abort
20235     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
20236     0f 85/jump-if-!= $array-element-type-id:error1/disp32
20237     # if (t->left == addr) t = t->right
20238     {
20239       50/push-eax
20240       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
20241       (is-simple-mu-type? %eax 2)  # addr => eax
20242       3d/compare-eax-with 0/imm32/false
20243       58/pop-to-eax
20244       74/jump-if-= break/disp8
20245 $array-element-type-id:skip-addr:
20246       (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
20247     }
20248     # if t == 0 abort
20249     3d/compare-eax-with 0/imm32
20250     0f 84/jump-if-= $array-element-type-id:error2/disp32
20251     # if t->is-atom? abort
20252     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
20253     0f 85/jump-if-!= $array-element-type-id:error2/disp32
20254     # if t->left != array abort
20255     {
20256       50/push-eax
20257       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
20258       (is-simple-mu-type? %eax 3)  # array => eax
20259       3d/compare-eax-with 0/imm32/false
20260       58/pop-to-eax
20261 $array-element-type-id:no-array:
20262       0f 84/jump-if-= $array-element-type-id:error2/disp32
20263     }
20264 $array-element-type-id:skip-array:
20265     # t = t->right
20266     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
20267     # if t == 0 abort
20268     3d/compare-eax-with 0/imm32
20269     0f 84/jump-if-= $array-element-type-id:error2/disp32
20270     # if t->is-atom? abort
20271     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
20272     0f 85/jump-if-!= $array-element-type-id:error2/disp32
20273     # t = t->left
20274     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
20275     # if (!t->is-atom?) t = t->left     # TODO: assumes array element size can be determined from just first word of array element type
20276     # if (t->is-atom == false) t = lookup(t->left)
20277     {
20278       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
20279       75/jump-if-!= break/disp8
20280       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
20281     }
20282     # return t->value
20283     8b/-> *(eax+4) 0/r32/eax  # Type-tree-value
20284 $array-element-type-id:end:
20285     # . epilogue
20286     89/<- %esp 5/r32/ebp
20287     5d/pop-to-ebp
20288     c3/return
20289 
20290 $array-element-type-id:error0:
20291     (write-buffered *(ebp+0xc) "array-element-type-id: var '")
20292     50/push-eax
20293     8b/-> *(ebp+8) 0/r32/eax
20294     (lookup *eax *(eax+4))  # Var-name Var-name => eax
20295     (write-buffered *(ebp+0xc) %eax)
20296     58/pop-to-eax
20297     (write-buffered *(ebp+0xc) "' has no type\n")
20298     (flush *(ebp+0xc))
20299     (stop *(ebp+0x10) 1)
20300     # never gets here
20301 
20302 $array-element-type-id:error1:
20303     (write-buffered *(ebp+0xc) "array-element-type-id: var '")
20304     50/push-eax
20305     8b/-> *(ebp+8) 0/r32/eax
20306     (lookup *eax *(eax+4))  # Var-name Var-name => eax
20307     (write-buffered *(ebp+0xc) %eax)
20308     58/pop-to-eax
20309     (write-buffered *(ebp+0xc) "' has atomic type ")
20310     (write-int32-hex-buffered *(ebp+0xc) *(eax+4))  # Type-tree-value
20311     (write-buffered *(ebp+0xc) Newline)
20312     (flush *(ebp+0xc))
20313     (stop *(ebp+0x10) 1)
20314     # never gets here
20315 
20316 $array-element-type-id:error2:
20317     (write-buffered *(ebp+0xc) "array-element-type-id: var '")
20318     50/push-eax
20319     8b/-> *(ebp+8) 0/r32/eax
20320     (lookup *eax *(eax+4))  # Var-name Var-name => eax
20321     (write-buffered *(ebp+0xc) %eax)
20322     58/pop-to-eax
20323     (write-buffered *(ebp+0xc) "' has non-array type\n")
20324     (flush *(ebp+0xc))
20325     (stop *(ebp+0x10) 1)
20326     # never gets here
20327 
20328 size-of-type-id-as-array-element:  # t: type-id -> result/eax: int
20329     # . prologue
20330     55/push-ebp
20331     89/<- %ebp 4/r32/esp
20332     # eax = t
20333     8b/-> *(ebp+8) 0/r32/eax
20334     # if t is 'byte', size is 1
20335     3d/compare-eax-and 8/imm32/byte
20336     {
20337       75/jump-if-!= break/disp8
20338       b8/copy-to-eax 1/imm32
20339       eb/jump $size-of-type-id-as-array-element:end/disp8
20340     }
20341     # otherwise proceed as usual
20342     (size-of-type-id %eax)  # => eax
20343 $size-of-type-id-as-array-element:end:
20344     # . epilogue
20345     89/<- %esp 5/r32/ebp
20346     5d/pop-to-ebp
20347     c3/return
20348 
20349 emit-save-size-to:  # out: (addr buffered-file), base: (addr var), outreg: (addr array byte)
20350     # . prologue
20351     55/push-ebp
20352     89/<- %ebp 4/r32/esp
20353     # . save registers
20354     50/push-eax
20355     53/push-ebx
20356     # ebx = base
20357     8b/-> *(ebp+0xc) 3/r32/ebx
20358     (emit-indent *(ebp+8) *Curr-block-depth)
20359     (write-buffered *(ebp+8) "8b/-> *")
20360     # if base is an (addr array ...) in a register
20361     {
20362       81 7/subop/compare *(ebx+0x18)) 0/imm32  # Var-register
20363       74/jump-if-= break/disp8
20364 $emit-save-size-to:emit-base-from-register:
20365       (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
20366       (write-buffered *(ebp+8) %eax)
20367       eb/jump $emit-save-size-to:emit-output/disp8
20368     }
20369     # otherwise if base is an (array ...) on the stack
20370     {
20371       81 7/subop/compare *(ebx+0x14)) 0/imm32  # Var-offset
20372       74/jump-if-= break/disp8
20373 $emit-save-size-to:emit-base-from-stack:
20374       (write-buffered *(ebp+8) "(ebp+")
20375       (write-int32-hex-buffered *(ebp+8) *(ebx+0x14))  # Var-offset
20376       (write-buffered *(ebp+8) ")")
20377     }
20378 $emit-save-size-to:emit-output:
20379     (write-buffered *(ebp+8) " ")
20380     (get Mu-registers *(ebp+0x10) 0xc "Mu-registers")  # => eax
20381     (write-int32-hex-buffered *(ebp+8) *eax)
20382     (write-buffered *(ebp+8) "/r32\n")
20383 $emit-save-size-to:end:
20384     # . restore registers
20385     5b/pop-to-ebx
20386     58/pop-to-eax
20387     # . epilogue
20388     89/<- %esp 5/r32/ebp
20389     5d/pop-to-ebp
20390     c3/return
20391 
20392 emit-divide-by-shift-right:  # out: (addr buffered-file), reg: (addr array byte), size: int
20393     # . prologue
20394     55/push-ebp
20395     89/<- %ebp 4/r32/esp
20396     # . save registers
20397     50/push-eax
20398     #
20399     (emit-indent *(ebp+8) *Curr-block-depth)
20400     (write-buffered *(ebp+8) "c1/shift 5/subop/>> %")
20401     (write-buffered *(ebp+8) *(ebp+0xc))
20402     (write-buffered *(ebp+8) Space)
20403     (num-shift-rights *(ebp+0x10))  # => eax
20404     (write-int32-hex-buffered *(ebp+8) %eax)
20405     (write-buffered *(ebp+8) "/imm8\n")
20406 $emit-divide-by-shift-right:end:
20407     # . restore registers
20408     58/pop-to-eax
20409     # . epilogue
20410     89/<- %esp 5/r32/ebp
20411     5d/pop-to-ebp
20412     c3/return
20413 
20414 translate-mu-index-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
20415     # . prologue
20416     55/push-ebp
20417     89/<- %ebp 4/r32/esp
20418     # . save registers
20419     51/push-ecx
20420     # ecx = stmt
20421     8b/-> *(ebp+0xc) 1/r32/ecx
20422     # var base/ecx: (addr var) = stmt->inouts[0]
20423     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
20424     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
20425     89/<- %ecx 0/r32/eax
20426     # if (var->register) do one thing
20427     {
20428       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
20429       74/jump-if-= break/disp8
20430       # TODO: ensure there's no dereference
20431       (translate-mu-index-stmt-with-array-in-register *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20432       eb/jump $translate-mu-index-stmt:end/disp8
20433     }
20434     # if (var->offset) do a different thing
20435     {
20436       81 7/subop/compare *(ecx+0x14) 0/imm32  # Var-offset
20437       74/jump-if-= break/disp8
20438       # TODO: ensure there's no dereference
20439       (translate-mu-index-stmt-with-array-on-stack *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20440       eb/jump $translate-mu-index-stmt:end/disp8
20441     }
20442 $translate-mu-index-stmt:end:
20443     # . restore registers
20444     59/pop-to-ecx
20445     # . epilogue
20446     89/<- %esp 5/r32/ebp
20447     5d/pop-to-ebp
20448     c3/return
20449 
20450 $translate-mu-index-stmt-with-array:error1:
20451     (write-buffered *(ebp+0x10) "couldn't translate an index instruction. second (index) input must either lie in a register or be a literal\n")
20452     (flush *(ebp+0x10))
20453     (stop *(ebp+0x14) 1)
20454     # never gets here
20455 
20456 $translate-mu-index-stmt-with-array:error2:
20457     (write-buffered *(ebp+0x10) "couldn't translate an index instruction. second (index) input when in a register must be an int or offset\n")
20458     (flush *(ebp+0x10))
20459     (stop *(ebp+0x14) 1)
20460     # never gets here
20461 
20462 translate-mu-index-stmt-with-array-in-register:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
20463     # . prologue
20464     55/push-ebp
20465     89/<- %ebp 4/r32/esp
20466     # . save registers
20467     50/push-eax
20468     51/push-ecx
20469     52/push-edx
20470     53/push-ebx
20471     #
20472     (emit-indent *(ebp+8) *Curr-block-depth)
20473     (write-buffered *(ebp+8) "8d/copy-address *(")
20474     # TODO: ensure inouts[0] is in a register and not dereferenced
20475 $translate-mu-index-stmt-with-array-in-register:emit-base:
20476     # ecx = stmt
20477     8b/-> *(ebp+0xc) 1/r32/ecx
20478     # var base/ebx: (addr var) = inouts[0]
20479     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
20480     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
20481     89/<- %ebx 0/r32/eax
20482     # print base->register " + "
20483     (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
20484     (write-buffered *(ebp+8) %eax)
20485     (write-buffered *(ebp+8) " + ")
20486     # var index/edx: (addr var) = inouts[1]
20487     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
20488     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
20489     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
20490     89/<- %edx 0/r32/eax
20491     # if index->register
20492     81 7/subop/compare *(edx+0x18) 0/imm32  # Var-register
20493     {
20494       0f 84/jump-if-= break/disp32
20495 $translate-mu-index-stmt-with-array-in-register:emit-register-index:
20496       # if index is an int
20497       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
20498       (is-simple-mu-type? %eax 1)  # int => eax
20499       3d/compare-eax-and 0/imm32/false
20500       {
20501         0f 84/jump-if-= break/disp32
20502 $translate-mu-index-stmt-with-array-in-register:emit-int-register-index:
20503         # print index->register "<<" log2(array-element-size(base)) " + 4) "
20504         # . index->register "<<"
20505         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
20506         (write-buffered *(ebp+8) %eax)
20507         (write-buffered *(ebp+8) "<<")
20508         # . log2(array-element-size(base->type))
20509         # TODO: ensure size is a power of 2
20510         (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
20511         (num-shift-rights %eax)  # => eax
20512         (write-int32-hex-buffered *(ebp+8) %eax)
20513         e9/jump $translate-mu-index-stmt-with-array-in-register:emit-register-index-done/disp32
20514       }
20515       # if index->type is any other atom, abort
20516       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
20517       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
20518       0f 85/jump-if-!= $translate-mu-index-stmt-with-array:error2/disp32
20519       # if index has type (offset ...)
20520       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
20521       (is-simple-mu-type? %eax 7)  # => eax
20522       3d/compare-eax-and 0/imm32/false
20523       {
20524         0f 84/jump-if-= break/disp32
20525         # print index->register
20526 $translate-mu-index-stmt-with-array-in-register:emit-offset-register-index:
20527         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
20528         (write-buffered *(ebp+8) %eax)
20529       }
20530 $translate-mu-index-stmt-with-array-in-register:emit-register-index-done:
20531       (write-buffered *(ebp+8) " + 4) ")
20532       e9/jump $translate-mu-index-stmt-with-array-in-register:emit-output/disp32
20533     }
20534     # otherwise if index is a literal
20535     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
20536     (is-simple-mu-type? %eax 0)  # => eax
20537     3d/compare-eax-and 0/imm32/false
20538     {
20539       0f 84/jump-if-= break/disp32
20540 $translate-mu-index-stmt-with-array-in-register:emit-literal-index:
20541       # var index-value/edx: int = parse-hex-int(index->name)
20542       (lookup *edx *(edx+4))  # Var-name Var-name => eax
20543       (parse-hex-int %eax)  # => eax
20544       89/<- %edx 0/r32/eax
20545       # offset = idx-value * array-element-size(base->type)
20546       (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
20547       f7 4/subop/multiply-into-edx-eax %edx  # clobbers edx
20548       # offset += 4 for array size
20549       05/add-to-eax 4/imm32
20550       # TODO: check edx for overflow
20551       # print offset
20552       (write-int32-hex-buffered *(ebp+8) %eax)
20553       (write-buffered *(ebp+8) ") ")
20554       e9/jump $translate-mu-index-stmt-with-array-in-register:emit-output/disp32
20555     }
20556     # otherwise abort
20557     e9/jump $translate-mu-index-stmt-with-array:error1/disp32
20558 $translate-mu-index-stmt-with-array-in-register:emit-output:
20559     # outputs[0] "/r32"
20560     8b/-> *(ebp+0xc) 1/r32/ecx
20561     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
20562     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
20563     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
20564     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
20565     (write-int32-hex-buffered *(ebp+8) *eax)
20566     (write-buffered *(ebp+8) "/r32\n")
20567 $translate-mu-index-stmt-with-array-in-register:end:
20568     # . restore registers
20569     5b/pop-to-ebx
20570     5a/pop-to-edx
20571     59/pop-to-ecx
20572     58/pop-to-eax
20573     # . epilogue
20574     89/<- %esp 5/r32/ebp
20575     5d/pop-to-ebp
20576     c3/return
20577 
20578 translate-mu-index-stmt-with-array-on-stack:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
20579     # . prologue
20580     55/push-ebp
20581     89/<- %ebp 4/r32/esp
20582     # . save registers
20583     50/push-eax
20584     51/push-ecx
20585     52/push-edx
20586     53/push-ebx
20587     #
20588     (emit-indent *(ebp+8) *Curr-block-depth)
20589     (write-buffered *(ebp+8) "8d/copy-address *(ebp + ")
20590     # var curr/edx: (addr stmt-var) = lookup(stmt->inouts)
20591     8b/-> *(ebp+0xc) 0/r32/eax
20592     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
20593     89/<- %edx 0/r32/eax
20594     # var base/ecx: (addr var) = lookup(curr->value)
20595     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
20596     89/<- %ecx 0/r32/eax
20597     # var curr2/eax: (addr stmt-var) = lookup(curr->next)
20598     (lookup *(edx+8) *(edx+0xc))  # Stmt-var-next Stmt-var-next => eax
20599     # var index/edx: (handle var) = curr2->value
20600     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
20601     89/<- %edx 0/r32/eax
20602     # if index->register
20603     81 7/subop/compare *(edx+0x18) 0/imm32  # Var-register
20604     {
20605       0f 84/jump-if-= break/disp32
20606 $translate-mu-index-stmt-with-array-on-stack:emit-register-index:
20607       # if index is an int
20608       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
20609       (is-simple-mu-type? %eax 1)  # int => eax
20610       3d/compare-eax-and 0/imm32/false
20611       {
20612         0f 84/jump-if-= break/disp32
20613 $translate-mu-index-stmt-with-array-on-stack:emit-int-register-index:
20614         # print index->register "<<" log2(array-element-size(base)) " + " base->offset+4
20615         # . inouts[1]->register "<<"
20616         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
20617         (write-buffered *(ebp+8) %eax)
20618         (write-buffered *(ebp+8) "<<")
20619         # . log2(array-element-size(base))
20620         # TODO: ensure size is a power of 2
20621         (array-element-size %ecx *(ebp+0x10) *(ebp+0x14))  # => eax
20622         (num-shift-rights %eax)  # => eax
20623         (write-int32-hex-buffered *(ebp+8) %eax)
20624         #
20625         (write-buffered *(ebp+8) " + ")
20626         #
20627         8b/-> *(ecx+0x14) 0/r32/eax  # Var-offset
20628         05/add-to-eax 4/imm32  # for array length
20629         (write-int32-hex-buffered *(ebp+8) %eax)
20630         e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-register-index-done/disp32
20631       }
20632       # if index->type is any other atom, abort
20633       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
20634       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
20635       0f 85/jump-if-!= $translate-mu-index-stmt-with-array:error2/disp32
20636       # if index has type (offset ...)
20637       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
20638       (is-simple-mu-type? %eax 7)  # => eax
20639       3d/compare-eax-and 0/imm32/false
20640       {
20641         0f 84/jump-if-= break/disp32
20642         # print index->register
20643 $translate-mu-index-stmt-with-array-on-stack:emit-offset-register-index:
20644         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
20645         (write-buffered *(ebp+8) %eax)
20646       }
20647 $translate-mu-index-stmt-with-array-on-stack:emit-register-index-done:
20648       (write-buffered *(ebp+8) ") ")
20649       e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-output/disp32
20650     }
20651     # otherwise if index is a literal
20652     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
20653     (is-simple-mu-type? %eax 0)  # => eax
20654     3d/compare-eax-and 0/imm32/false
20655     {
20656       0f 84/jump-if-= break/disp32
20657 $translate-mu-index-stmt-with-array-on-stack:emit-literal-index:
20658       # var idx-value/edx: int = parse-hex-int(index->name)
20659       (lookup *edx *(edx+4))  # Var-name Var-name => eax
20660       (parse-hex-int %eax)  # Var-name => eax
20661       89/<- %edx 0/r32/eax
20662       # offset = idx-value * array-element-size(base)
20663       (array-element-size %ecx *(ebp+0x10) *(ebp+0x14))  # => eax
20664       f7 4/subop/multiply-into-edx-eax %edx  # clobbers edx
20665       # offset += base->offset
20666       03/add *(ecx+0x14) 0/r32/eax  # Var-offset
20667       # offset += 4 for array size
20668       05/add-to-eax 4/imm32
20669       # TODO: check edx for overflow
20670       # print offset
20671       (write-int32-hex-buffered *(ebp+8) %eax)
20672       (write-buffered *(ebp+8) ") ")
20673       e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-output/disp32
20674     }
20675     # otherwise abort
20676     e9/jump $translate-mu-index-stmt-with-array:error1/disp32
20677 $translate-mu-index-stmt-with-array-on-stack:emit-output:
20678     # outputs[0] "/r32"
20679     8b/-> *(ebp+0xc) 0/r32/eax
20680     (lookup *(eax+0x14) *(eax+0x18))  # Stmt1-outputs Stmt1-outputs => eax
20681     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
20682     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
20683     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
20684     (write-int32-hex-buffered *(ebp+8) *eax)
20685     (write-buffered *(ebp+8) "/r32\n")
20686 $translate-mu-index-stmt-with-array-on-stack:end:
20687     # . restore registers
20688     5b/pop-to-ebx
20689     5a/pop-to-edx
20690     59/pop-to-ecx
20691     58/pop-to-eax
20692     # . epilogue
20693     89/<- %esp 5/r32/ebp
20694     5d/pop-to-ebp
20695     c3/return
20696 
20697 translate-mu-compute-index-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
20698     # . prologue
20699     55/push-ebp
20700     89/<- %ebp 4/r32/esp
20701     # . save registers
20702     50/push-eax
20703     51/push-ecx
20704     52/push-edx
20705     53/push-ebx
20706     #
20707     (emit-indent *(ebp+8) *Curr-block-depth)
20708     (write-buffered *(ebp+8) "69/multiply")
20709     # ecx = stmt
20710     8b/-> *(ebp+0xc) 1/r32/ecx
20711     # var first-inout/ebx: (addr stmt-var) = stmt->inouts[0]
20712     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
20713     89/<- %ebx 0/r32/eax
20714 $translate-mu-compute-index-stmt:emit-index:
20715     (lookup *(ebx+8) *(ebx+0xc))  # Stmt-var-next Stmt-var-next => eax
20716     (emit-subx-var-as-rm32 *(ebp+8) %eax)
20717     (write-buffered *(ebp+8) Space)
20718 $translate-mu-compute-index-stmt:emit-elem-size:
20719     # var base/ebx: (addr var)
20720     (lookup *ebx *(ebx+4))  # Stmt-var-value Stmt-var-value => eax
20721     89/<- %ebx 0/r32/eax
20722     # print array-element-size(base)
20723     (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
20724     (write-int32-hex-buffered *(ebp+8) %eax)
20725     (write-buffered *(ebp+8) "/imm32 ")
20726 $translate-mu-compute-index-stmt:emit-output:
20727     # outputs[0] "/r32"
20728     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
20729     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
20730     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
20731     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
20732     (write-int32-hex-buffered *(ebp+8) *eax)
20733     (write-buffered *(ebp+8) "/r32\n")
20734 $translate-mu-compute-index-stmt:end:
20735     # . restore registers
20736     5b/pop-to-ebx
20737     5a/pop-to-edx
20738     59/pop-to-ecx
20739     58/pop-to-eax
20740     # . epilogue
20741     89/<- %esp 5/r32/ebp
20742     5d/pop-to-ebp
20743     c3/return
20744 
20745 translate-mu-get-stmt:  # out: (addr buffered-file), stmt: (addr stmt)
20746     # . prologue
20747     55/push-ebp
20748     89/<- %ebp 4/r32/esp
20749     # . save registers
20750     50/push-eax
20751     51/push-ecx
20752     52/push-edx
20753     #
20754     (emit-indent *(ebp+8) *Curr-block-depth)
20755     (write-buffered *(ebp+8) "8d/copy-address ")
20756     # ecx = stmt
20757     8b/-> *(ebp+0xc) 1/r32/ecx
20758     # var offset/edx: int = get offset of stmt
20759     (mu-get-offset %ecx)  # => eax
20760     89/<- %edx 0/r32/eax
20761     # var base/eax: (addr var) = stmt->inouts->value
20762     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
20763     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
20764     # if base is in a register
20765     81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
20766     {
20767       0f 84/jump-if-= break/disp32
20768 $translate-mu-get-stmt:emit-register-input:
20769       # emit "*(" base->register " + " offset ") "
20770       (write-buffered *(ebp+8) "*(")
20771       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
20772       (write-buffered *(ebp+8) %eax)
20773       (write-buffered *(ebp+8) " + ")
20774       (write-int32-hex-buffered *(ebp+8) %edx)
20775       (write-buffered *(ebp+8) ") ")
20776       e9/jump $translate-mu-get-stmt:emit-output/disp32
20777     }
20778     # otherwise base is on the stack
20779     {
20780 $translate-mu-get-stmt:emit-stack-input:
20781       # emit "*(ebp + " inouts[0]->stack-offset + offset ") "
20782       (write-buffered *(ebp+8) "*(ebp+")
20783       03/add *(eax+0x14) 2/r32/edx  # Var-offset
20784       (write-int32-hex-buffered *(ebp+8) %edx)
20785       (write-buffered *(ebp+8) ") ")
20786       eb/jump $translate-mu-get-stmt:emit-output/disp8
20787     }
20788 $translate-mu-get-stmt:emit-output:
20789     # var output/eax: (addr var) = stmt->outputs->value
20790     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
20791     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
20792     # emit offset->register "/r32"
20793     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
20794     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
20795     (write-int32-hex-buffered *(ebp+8) *eax)
20796     (write-buffered *(ebp+8) "/r32\n")
20797 $translate-mu-get-stmt:end:
20798     # . restore registers
20799     5a/pop-to-edx
20800     59/pop-to-ecx
20801     58/pop-to-eax
20802     # . epilogue
20803     89/<- %esp 5/r32/ebp
20804     5d/pop-to-ebp
20805     c3/return
20806 
20807 translate-mu-copy-object-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
20808     # . prologue
20809     55/push-ebp
20810     89/<- %ebp 4/r32/esp
20811     # . save registers
20812     50/push-eax
20813     #
20814     (emit-indent *(ebp+8) *Curr-block-depth)
20815     (write-buffered *(ebp+8) "(copy-bytes")
20816     # eax = stmt
20817     8b/-> *(ebp+0xc) 0/r32/eax
20818     # var first-inout/eax: (addr stmt-var) = stmt->inouts[0]
20819     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
20820     (emit-subx-call-operand *(ebp+8) %eax)
20821     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
20822     (emit-subx-call-operand *(ebp+8) %eax)
20823     (write-buffered *(ebp+8) Space)
20824     (addr-payload-size %eax *(ebp+0x10) *(ebp+0x14))  # => eax
20825     (write-int32-hex-buffered *(ebp+8) %eax)
20826     (write-buffered *(ebp+8) ")\n")
20827 $translate-mu-copy-object-stmt:end:
20828     # . restore registers
20829     58/pop-to-eax
20830     # . epilogue
20831     89/<- %esp 5/r32/ebp
20832     5d/pop-to-ebp
20833     c3/return
20834 
20835 translate-mu-allocate-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
20836     # . prologue
20837     55/push-ebp
20838     89/<- %ebp 4/r32/esp
20839     # . save registers
20840     50/push-eax
20841     56/push-esi
20842     57/push-edi
20843     # esi = stmt
20844     8b/-> *(ebp+0xc) 6/r32/esi
20845     # var target/edi: (addr stmt-var) = stmt->inouts[0]
20846     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
20847     89/<- %edi 0/r32/eax
20848     #
20849     (emit-indent *(ebp+8) *Curr-block-depth)
20850     (write-buffered *(ebp+8) "(allocate Heap ")
20851     (addr-handle-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
20852     (write-int32-hex-buffered *(ebp+8) %eax)
20853     (emit-subx-call-operand *(ebp+8) %edi)
20854     (write-buffered *(ebp+8) ")\n")
20855 $translate-mu-allocate-stmt:end:
20856     # . restore registers
20857     5f/pop-to-edi
20858     5e/pop-to-esi
20859     58/pop-to-eax
20860     # . epilogue
20861     89/<- %esp 5/r32/ebp
20862     5d/pop-to-ebp
20863     c3/return
20864 
20865 addr-handle-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
20866     # . prologue
20867     55/push-ebp
20868     89/<- %ebp 4/r32/esp
20869     # var t/eax: (addr type-tree) = s->value->type
20870     8b/-> *(ebp+8) 0/r32/eax
20871     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
20872     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20873     # TODO: check eax != 0
20874     # TODO: check !t->is-atom?
20875     # TODO: check t->left == addr
20876     # t = t->right
20877 $addr-handle-payload-size:skip-addr:
20878     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
20879     # TODO: check eax != 0
20880     # TODO: check !t->is-atom?
20881     # TODO: check t->left == handle
20882     # t = t->right
20883 $addr-handle-payload-size:skip-handle:
20884     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
20885     # TODO: check eax != 0
20886     # if !t->is-atom? t = t->left
20887     81 7/subop/compare *eax 0/imm32/false
20888     {
20889       75/jump-if-!= break/disp8
20890       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
20891     }
20892     # TODO: check t->is-atom?
20893     # return size(t->value)
20894     (size-of-type-id *(eax+4))  # Type-tree-value => eax
20895 $addr-handle-payload-size:end:
20896     # . epilogue
20897     89/<- %esp 5/r32/ebp
20898     5d/pop-to-ebp
20899     c3/return
20900 
20901 addr-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
20902     # . prologue
20903     55/push-ebp
20904     89/<- %ebp 4/r32/esp
20905     # var t/eax: (addr type-tree) = s->value->type
20906     8b/-> *(ebp+8) 0/r32/eax
20907     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
20908     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20909     # TODO: check eax != 0
20910     # TODO: check !t->is-atom?
20911     # TODO: check t->left == addr
20912     # t = t->right
20913 $addr-payload-size:skip-addr:
20914     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
20915     # TODO: check eax != 0
20916     # if !t->is-atom? t = t->left
20917     81 7/subop/compare *eax 0/imm32/false
20918     {
20919       75/jump-if-!= break/disp8
20920       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
20921     }
20922     # TODO: check t->is-atom?
20923     # return size(t->value)
20924     (size-of-type-id *(eax+4))  # Type-tree-value => eax
20925 $addr-payload-size:end:
20926     # . epilogue
20927     89/<- %esp 5/r32/ebp
20928     5d/pop-to-ebp
20929     c3/return
20930 
20931 translate-mu-populate-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
20932     # . prologue
20933     55/push-ebp
20934     89/<- %ebp 4/r32/esp
20935     # . save registers
20936     50/push-eax
20937     51/push-ecx
20938     56/push-esi
20939     57/push-edi
20940     # esi = stmt
20941     8b/-> *(ebp+0xc) 6/r32/esi
20942     # var target/edi: (addr stmt-var) = stmt->inouts[0]
20943     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
20944     89/<- %edi 0/r32/eax
20945     # var len/ecx: (addr stmt-var) = stmt->inouts[1]
20946     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
20947     89/<- %ecx 0/r32/eax
20948     #
20949     (emit-indent *(ebp+8) *Curr-block-depth)
20950     (write-buffered *(ebp+8) "(allocate-array2 Heap ")
20951     (addr-handle-array-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
20952     (write-int32-hex-buffered *(ebp+8) %eax)
20953     (emit-subx-call-operand *(ebp+8) %ecx)
20954     (emit-subx-call-operand *(ebp+8) %edi)
20955     (write-buffered *(ebp+8) ")\n")
20956 $translate-mu-populate-stmt:end:
20957     # . restore registers
20958     5f/pop-to-edi
20959     5e/pop-to-esi
20960     59/pop-to-ecx
20961     58/pop-to-eax
20962     # . epilogue
20963     89/<- %esp 5/r32/ebp
20964     5d/pop-to-ebp
20965     c3/return
20966 
20967 translate-mu-populate-stream-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
20968     # . prologue
20969     55/push-ebp
20970     89/<- %ebp 4/r32/esp
20971     # . save registers
20972     50/push-eax
20973     51/push-ecx
20974     56/push-esi
20975     57/push-edi
20976     # esi = stmt
20977     8b/-> *(ebp+0xc) 6/r32/esi
20978     # var target/edi: (addr stmt-var) = stmt->inouts[0]
20979     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
20980     89/<- %edi 0/r32/eax
20981     # var len/ecx: (addr stmt-var) = stmt->inouts[1]
20982     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
20983     89/<- %ecx 0/r32/eax
20984     #
20985     (emit-indent *(ebp+8) *Curr-block-depth)
20986     (write-buffered *(ebp+8) "(new-stream Heap ")
20987     (addr-handle-stream-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
20988     (write-int32-hex-buffered *(ebp+8) %eax)
20989     (emit-subx-call-operand *(ebp+8) %ecx)
20990     (emit-subx-call-operand *(ebp+8) %edi)
20991     (write-buffered *(ebp+8) ")\n")
20992 $translate-mu-populate-stream-stmt:end:
20993     # . restore registers
20994     5f/pop-to-edi
20995     5e/pop-to-esi
20996     59/pop-to-ecx
20997     58/pop-to-eax
20998     # . epilogue
20999     89/<- %esp 5/r32/ebp
21000     5d/pop-to-ebp
21001     c3/return
21002 
21003 translate-mu-read-from-stream-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
21004     # . prologue
21005     55/push-ebp
21006     89/<- %ebp 4/r32/esp
21007     # . save registers
21008     50/push-eax
21009     51/push-ecx
21010     56/push-esi
21011     57/push-edi
21012     # esi = stmt
21013     8b/-> *(ebp+0xc) 6/r32/esi
21014     # var stream/ecx: (addr stmt-var) = stmt->inouts[0]
21015     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
21016     89/<- %ecx 0/r32/eax
21017     # var target/edi: (addr stmt-var) = stmt->inouts[1]
21018     (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
21019     89/<- %edi 0/r32/eax
21020     #
21021     (emit-indent *(ebp+8) *Curr-block-depth)
21022     (write-buffered *(ebp+8) "(read-from-stream")
21023     (emit-subx-call-operand *(ebp+8) %ecx)
21024     (emit-subx-call-operand *(ebp+8) %edi)
21025     (write-buffered *(ebp+8) Space)
21026     (addr-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
21027     (write-int32-hex-buffered *(ebp+8) %eax)
21028     (write-buffered *(ebp+8) ")\n")
21029 $translate-mu-read-from-stream-stmt:end:
21030     # . restore registers
21031     5f/pop-to-edi
21032     5e/pop-to-esi
21033     59/pop-to-ecx
21034     58/pop-to-eax
21035     # . epilogue
21036     89/<- %esp 5/r32/ebp
21037     5d/pop-to-ebp
21038     c3/return
21039 
21040 translate-mu-write-to-stream-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
21041     # . prologue
21042     55/push-ebp
21043     89/<- %ebp 4/r32/esp
21044     # . save registers
21045     50/push-eax
21046     51/push-ecx
21047     56/push-esi
21048     57/push-edi
21049     # esi = stmt
21050     8b/-> *(ebp+0xc) 6/r32/esi
21051     # var stream/ecx: (addr stmt-var) = stmt->inouts[0]
21052     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
21053     89/<- %ecx 0/r32/eax
21054     # var target/edi: (addr stmt-var) = stmt->inouts[1]
21055     (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
21056     89/<- %edi 0/r32/eax
21057     #
21058     (emit-indent *(ebp+8) *Curr-block-depth)
21059     (write-buffered *(ebp+8) "(write-to-stream")
21060     (emit-subx-call-operand *(ebp+8) %ecx)
21061     (flush *(ebp+8))
21062     (emit-subx-call-operand *(ebp+8) %edi)
21063     (flush *(ebp+8))
21064     (write-buffered *(ebp+8) Space)
21065     (flush *(ebp+8))
21066     (addr-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
21067     (write-int32-hex-buffered *(ebp+8) %eax)
21068     (write-buffered *(ebp+8) ")\n")
21069 $translate-mu-write-to-stream-stmt:end:
21070     # . restore registers
21071     5f/pop-to-edi
21072     5e/pop-to-esi
21073     59/pop-to-ecx
21074     58/pop-to-eax
21075     # . epilogue
21076     89/<- %esp 5/r32/ebp
21077     5d/pop-to-ebp
21078     c3/return
21079 
21080 addr-handle-array-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
21081     # . prologue
21082     55/push-ebp
21083     89/<- %ebp 4/r32/esp
21084     # var t/eax: (addr type-tree) = s->value->type
21085     8b/-> *(ebp+8) 0/r32/eax
21086     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
21087     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
21088     # TODO: check eax != 0
21089     # TODO: check !t->is-atom?
21090     # TODO: check t->left == addr
21091     # t = t->right
21092 $addr-handle-array-payload-size:skip-addr:
21093     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
21094     # TODO: check eax != 0
21095     # TODO: check !t->is-atom?
21096     # TODO: check t->left == handle
21097     # t = t->right
21098 $addr-handle-array-payload-size:skip-handle:
21099     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
21100     # TODO: check eax != 0
21101     # TODO: check !t->is-atom?
21102     # TODO: check t->left == array
21103     # t = t->right
21104 $addr-handle-array-payload-size:skip-array:
21105     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
21106     # TODO: check eax != 0
21107     # if !t->is-atom? t = t->left
21108     81 7/subop/compare *eax 0/imm32/false
21109     {
21110       75/jump-if-!= break/disp8
21111       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
21112     }
21113 $addr-handle-array-payload-size:compute-size:
21114     # TODO: check t->is-atom?
21115     # return size(t->value)
21116     (size-of-type-id-as-array-element *(eax+4))  # Type-tree-value => eax
21117 $addr-handle-array-payload-size:end:
21118     # . epilogue
21119     89/<- %esp 5/r32/ebp
21120     5d/pop-to-ebp
21121     c3/return
21122 
21123 addr-handle-stream-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
21124     # . prologue
21125     55/push-ebp
21126     89/<- %ebp 4/r32/esp
21127     # var t/eax: (addr type-tree) = s->value->type
21128     8b/-> *(ebp+8) 0/r32/eax
21129     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
21130     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
21131     # TODO: check eax != 0
21132     # TODO: check !t->is-atom?
21133     # TODO: check t->left == addr
21134     # t = t->right
21135 $addr-handle-stream-payload-size:skip-addr:
21136     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
21137     # TODO: check eax != 0
21138     # TODO: check !t->is-atom?
21139     # TODO: check t->left == handle
21140     # t = t->right
21141 $addr-handle-stream-payload-size:skip-handle:
21142     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
21143     # TODO: check eax != 0
21144     # TODO: check !t->is-atom?
21145     # TODO: check t->left == stream
21146     # t = t->right
21147 $addr-handle-stream-payload-size:skip-stream:
21148     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
21149     # TODO: check eax != 0
21150     # if !t->is-atom? t = t->left
21151     81 7/subop/compare *eax 0/imm32/false
21152     {
21153       75/jump-if-!= break/disp8
21154       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
21155     }
21156 $addr-handle-stream-payload-size:compute-size:
21157     # TODO: check t->is-atom?
21158     # return size(t->value)
21159     (size-of-type-id-as-array-element *(eax+4))  # Type-tree-value => eax
21160 $addr-handle-stream-payload-size:end:
21161     # . epilogue
21162     89/<- %esp 5/r32/ebp
21163     5d/pop-to-ebp
21164     c3/return
21165 
21166 power-of-2?:  # n: int, err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: boolean
21167     # precondition: n is positive
21168     # . prologue
21169     55/push-ebp
21170     89/<- %ebp 4/r32/esp
21171     # eax = n
21172     8b/-> *(ebp+8) 0/r32/eax
21173     # if (n < 0) abort
21174     3d/compare-eax-with 0/imm32
21175     0f 8c/jump-if-< $power-of-2?:abort/disp32
21176     # var tmp/eax: int = n-1
21177     48/decrement-eax
21178     # var tmp2/eax: int = n & tmp
21179     23/and-> *(ebp+8) 0/r32/eax
21180     # return (tmp2 == 0)
21181     3d/compare-eax-and 0/imm32
21182     0f 94/set-byte-if-= %al
21183     81 4/subop/and %eax 0xff/imm32
21184 $power-of-2?:end:
21185     # . epilogue
21186     89/<- %esp 5/r32/ebp
21187     5d/pop-to-ebp
21188     c3/return
21189 
21190 $power-of-2?:abort:
21191     (write-buffered *(ebp+0xc) "power-of-2?: negative number\n")
21192     (flush *(ebp+0xc))
21193     (stop *(ebp+0x10) 1)
21194     # never gets here
21195 
21196 num-shift-rights:  # n: int -> result/eax: int
21197     # precondition: n is a positive power of 2
21198     # . prologue
21199     55/push-ebp
21200     89/<- %ebp 4/r32/esp
21201     # . save registers
21202     51/push-ecx
21203     # var curr/ecx: int = n
21204     8b/-> *(ebp+8) 1/r32/ecx
21205     # result = 0
21206     b8/copy-to-eax 0/imm32
21207     {
21208       # if (curr <= 1) break
21209       81 7/subop/compare %ecx 1/imm32
21210       7e/jump-if-<= break/disp8
21211       40/increment-eax
21212       c1/shift 5/subop/arithmetic-right %ecx 1/imm8
21213       eb/jump loop/disp8
21214     }
21215 $num-shift-rights:end:
21216     # . restore registers
21217     59/pop-to-ecx
21218     # . epilogue
21219     89/<- %esp 5/r32/ebp
21220     5d/pop-to-ebp
21221     c3/return
21222 
21223 mu-get-offset:  # stmt: (addr stmt) -> result/eax: int
21224     # . prologue
21225     55/push-ebp
21226     89/<- %ebp 4/r32/esp
21227     # var second-inout/eax: (addr stmt-var) = stmt->inouts->next
21228     8b/-> *(ebp+8) 0/r32/eax
21229     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
21230     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
21231     # var output-var/eax: (addr var) = second-inout->value
21232     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
21233 #?     (write-buffered Stderr "mu-get-offset: ")
21234 #?     (write-int32-hex-buffered Stderr %eax)
21235 #?     (write-buffered Stderr " name: ")
21236 #?     50/push-eax
21237 #?     (lookup *eax *(eax+4))  # Var-name
21238 #?     (write-buffered Stderr %eax)
21239 #?     58/pop-to-eax
21240 #?     (write-buffered Stderr Newline)
21241 #?     (flush Stderr)
21242     # return output-var->stack-offset
21243     8b/-> *(eax+0x14) 0/r32/eax  # Var-offset
21244 #?     (write-buffered Stderr "=> ")
21245 #?     (write-int32-hex-buffered Stderr %eax)
21246 #?     (write-buffered Stderr Newline)
21247 #?     (flush Stderr)
21248 $emit-get-offset:end:
21249     # . epilogue
21250     89/<- %esp 5/r32/ebp
21251     5d/pop-to-ebp
21252     c3/return
21253 
21254 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)
21255     # . prologue
21256     55/push-ebp
21257     89/<- %ebp 4/r32/esp
21258     # . save registers
21259     50/push-eax
21260     51/push-ecx
21261     56/push-esi
21262     # esi = block
21263     8b/-> *(ebp+0xc) 6/r32/esi
21264     # block->var->block-depth = *Curr-block-depth
21265     (lookup *(esi+0xc) *(esi+0x10))  # Block-var Block-var => eax
21266     8b/-> *Curr-block-depth 1/r32/ecx
21267     89/<- *(eax+0x10) 1/r32/ecx  # Var-block-depth
21268     # var stmts/eax: (addr list stmt) = lookup(block->statements)
21269     (lookup *(esi+4) *(esi+8))  # Block-stmts Block-stmts => eax
21270     #
21271     {
21272 $emit-subx-block:check-empty:
21273       3d/compare-eax-and 0/imm32
21274       0f 84/jump-if-= break/disp32
21275       (emit-indent *(ebp+8) *Curr-block-depth)
21276       (write-buffered *(ebp+8) "{\n")
21277       # var v/ecx: (addr var) = lookup(block->var)
21278       (lookup *(esi+0xc) *(esi+0x10))  # Block-var Block-var => eax
21279       89/<- %ecx 0/r32/eax
21280       #
21281       (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
21282       (write-buffered *(ebp+8) %eax)
21283       (write-buffered *(ebp+8) ":loop:\n")
21284       ff 0/subop/increment *Curr-block-depth
21285       (push *(ebp+0x10) *(esi+0xc))  # Block-var
21286       (push *(ebp+0x10) *(esi+0x10))  # Block-var
21287       (push *(ebp+0x10) 0)  # false
21288       # emit block->statements
21289       (lookup *(esi+4) *(esi+8))  # Block-stmts Block-stmts => eax
21290       (emit-subx-stmt-list *(ebp+8) %eax *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
21291       (pop *(ebp+0x10))  # => eax
21292       (pop *(ebp+0x10))  # => eax
21293       (pop *(ebp+0x10))  # => eax
21294       ff 1/subop/decrement *Curr-block-depth
21295       (emit-indent *(ebp+8) *Curr-block-depth)
21296       (write-buffered *(ebp+8) "}\n")
21297       (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
21298       (write-buffered *(ebp+8) %eax)
21299       (write-buffered *(ebp+8) ":break:\n")
21300     }
21301 $emit-subx-block:end:
21302     # . restore registers
21303     5e/pop-to-esi
21304     59/pop-to-ecx
21305     58/pop-to-eax
21306     # . epilogue
21307     89/<- %esp 5/r32/ebp
21308     5d/pop-to-ebp
21309     c3/return
21310 
21311 # Primitives supported
21312 # See mu_instructions for a summary of this linked-list data structure.
21313 #
21314 # For each operation, put variants with hard-coded registers before flexible ones.
21315 #
21316 # Unfortunately, our restrictions on addresses require that various fields in
21317 # primitives be handles, which complicates these definitions.
21318 #   - we need to insert dummy fields all over the place for fake alloc-ids
21319 #   - we can't use our syntax sugar of quoted literals for string fields
21320 #
21321 # Fake alloc-ids are needed because our type definitions up top require
21322 # handles but it's clearer to statically allocate these long-lived objects.
21323 # Fake alloc-ids are perfectly safe, but they can't be reclaimed.
21324 #
21325 # Every 'object' below starts with a fake alloc-id. It may also contain other
21326 # fake alloc-ids for various handle fields.
21327 #
21328 # I think of objects starting with a fake alloc-id as having type 'payload'.
21329 # It's not really intended to be created dynamically; for that use `allocate`
21330 # as usual.
21331 #
21332 # Idea for a notation to simplify such definitions:
21333 #   _Primitive-increment-eax:  # (payload primitive)
21334 #     0x11/alloc-id:fake:payload
21335 #     0x11 @(0x11 "increment")  # name
21336 #     0 0                       # inouts
21337 #     0x11 @(0x11/payload
21338 #            0x11 @(0x11/payload  # List-value
21339 #                   0 0             # Var-name
21340 #                   0x11 @(0x11     # Var-type
21341 #                          1/is-atom
21342 #                          1/value 0/unused   # Type-tree-left
21343 #                          0 0                # Type-tree-right
21344 #                         )
21345 #                   1               # block-depth
21346 #                   0               # stack-offset
21347 #                   0x11 @(0x11 "eax")  # Var-register
21348 #                  )
21349 #            0 0)                 # List-next
21350 #     ...
21351 #     _Primitive-increment-ecx/imm32/next
21352 #   ...
21353 # Awfully complex and non-obvious. But also clearly signals there's something
21354 # to learn here, so may be worth trying.
21355 #
21356 # '@' is just an initial thought. Punctuation used so far in Mu: () * % # / "
21357 #
21358 # For now we'll continue to just use comments and manually ensure they stay up
21359 # to date.
21360 == data
21361 Primitives:  # (addr primitive)
21362 # - increment/decrement
21363 _Primitive-increment-eax:  # (addr primitive)
21364     # var/eax <- increment => 40/increment-eax
21365     0x11/imm32/alloc-id:fake
21366     _string-increment/imm32/name
21367     0/imm32/no-inouts
21368     0/imm32/no-inouts
21369     0x11/imm32/alloc-id:fake
21370     Single-int-var-in-eax/imm32/outputs
21371     0x11/imm32/alloc-id:fake
21372     _string_40_increment_eax/imm32/subx-name
21373     0/imm32/no-rm32
21374     0/imm32/no-r32
21375     0/imm32/no-imm32
21376     0/imm32/no-imm8
21377     0/imm32/no-disp32
21378     0/imm32/no-xm32
21379     0/imm32/no-x32
21380     0x11/imm32/alloc-id:fake
21381     _Primitive-increment-ecx/imm32/next
21382 _Primitive-increment-ecx:  # (payload primitive)
21383     0x11/imm32/alloc-id:fake:payload
21384     # var/ecx <- increment => 41/increment-ecx
21385     0x11/imm32/alloc-id:fake
21386     _string-increment/imm32/name
21387     0/imm32/no-inouts
21388     0/imm32/no-inouts
21389     0x11/imm32/alloc-id:fake
21390     Single-int-var-in-ecx/imm32/outputs
21391     0x11/imm32/alloc-id:fake
21392     _string_41_increment_ecx/imm32/subx-name
21393     0/imm32/no-rm32
21394     0/imm32/no-r32
21395     0/imm32/no-imm32
21396     0/imm32/no-imm8
21397     0/imm32/no-disp32
21398     0/imm32/no-xm32
21399     0/imm32/no-x32
21400     0x11/imm32/alloc-id:fake
21401     _Primitive-increment-edx/imm32/next
21402 _Primitive-increment-edx:  # (payload primitive)
21403     0x11/imm32/alloc-id:fake:payload
21404     # var/edx <- increment => 42/increment-edx
21405     0x11/imm32/alloc-id:fake
21406     _string-increment/imm32/name
21407     0/imm32/no-inouts
21408     0/imm32/no-inouts
21409     0x11/imm32/alloc-id:fake
21410     Single-int-var-in-edx/imm32/outputs
21411     0x11/imm32/alloc-id:fake
21412     _string_42_increment_edx/imm32/subx-name
21413     0/imm32/no-rm32
21414     0/imm32/no-r32
21415     0/imm32/no-imm32
21416     0/imm32/no-imm8
21417     0/imm32/no-disp32
21418     0/imm32/no-xm32
21419     0/imm32/no-x32
21420     0x11/imm32/alloc-id:fake
21421     _Primitive-increment-ebx/imm32/next
21422 _Primitive-increment-ebx:  # (payload primitive)
21423     0x11/imm32/alloc-id:fake:payload
21424     # var/ebx <- increment => 43/increment-ebx
21425     0x11/imm32/alloc-id:fake
21426     _string-increment/imm32/name
21427     0/imm32/no-inouts
21428     0/imm32/no-inouts
21429     0x11/imm32/alloc-id:fake
21430     Single-int-var-in-ebx/imm32/outputs
21431     0x11/imm32/alloc-id:fake
21432     _string_43_increment_ebx/imm32/subx-name
21433     0/imm32/no-rm32
21434     0/imm32/no-r32
21435     0/imm32/no-imm32
21436     0/imm32/no-imm8
21437     0/imm32/no-disp32
21438     0/imm32/no-xm32
21439     0/imm32/no-x32
21440     0x11/imm32/alloc-id:fake
21441     _Primitive-increment-esi/imm32/next
21442 _Primitive-increment-esi:  # (payload primitive)
21443     0x11/imm32/alloc-id:fake:payload
21444     # var/esi <- increment => 46/increment-esi
21445     0x11/imm32/alloc-id:fake
21446     _string-increment/imm32/name
21447     0/imm32/no-inouts
21448     0/imm32/no-inouts
21449     0x11/imm32/alloc-id:fake
21450     Single-int-var-in-esi/imm32/outputs
21451     0x11/imm32/alloc-id:fake
21452     _string_46_increment_esi/imm32/subx-name
21453     0/imm32/no-rm32
21454     0/imm32/no-r32
21455     0/imm32/no-imm32
21456     0/imm32/no-imm8
21457     0/imm32/no-disp32
21458     0/imm32/no-xm32
21459     0/imm32/no-x32
21460     0x11/imm32/alloc-id:fake
21461     _Primitive-increment-edi/imm32/next
21462 _Primitive-increment-edi:  # (payload primitive)
21463     0x11/imm32/alloc-id:fake:payload
21464     # var/edi <- increment => 47/increment-edi
21465     0x11/imm32/alloc-id:fake
21466     _string-increment/imm32/name
21467     0/imm32/no-inouts
21468     0/imm32/no-inouts
21469     0x11/imm32/alloc-id:fake
21470     Single-int-var-in-edi/imm32/outputs
21471     0x11/imm32/alloc-id:fake
21472     _string_47_increment_edi/imm32/subx-name
21473     0/imm32/no-rm32
21474     0/imm32/no-r32
21475     0/imm32/no-imm32
21476     0/imm32/no-imm8
21477     0/imm32/no-disp32
21478     0/imm32/no-xm32
21479     0/imm32/no-x32
21480     0x11/imm32/alloc-id:fake
21481     _Primitive-decrement-eax/imm32/next
21482 _Primitive-decrement-eax:  # (payload primitive)
21483     0x11/imm32/alloc-id:fake:payload
21484     # var/eax <- decrement => 48/decrement-eax
21485     0x11/imm32/alloc-id:fake
21486     _string-decrement/imm32/name
21487     0/imm32/no-inouts
21488     0/imm32/no-inouts
21489     0x11/imm32/alloc-id:fake
21490     Single-int-var-in-eax/imm32/outputs
21491     0x11/imm32/alloc-id:fake
21492     _string_48_decrement_eax/imm32/subx-name
21493     0/imm32/no-rm32
21494     0/imm32/no-r32
21495     0/imm32/no-imm32
21496     0/imm32/no-imm8
21497     0/imm32/no-disp32
21498     0/imm32/no-xm32
21499     0/imm32/no-x32
21500     0x11/imm32/alloc-id:fake
21501     _Primitive-decrement-ecx/imm32/next
21502 _Primitive-decrement-ecx:  # (payload primitive)
21503     0x11/imm32/alloc-id:fake:payload
21504     # var/ecx <- decrement => 49/decrement-ecx
21505     0x11/imm32/alloc-id:fake
21506     _string-decrement/imm32/name
21507     0/imm32/no-inouts
21508     0/imm32/no-inouts
21509     0x11/imm32/alloc-id:fake
21510     Single-int-var-in-ecx/imm32/outputs
21511     0x11/imm32/alloc-id:fake
21512     _string_49_decrement_ecx/imm32/subx-name
21513     0/imm32/no-rm32
21514     0/imm32/no-r32
21515     0/imm32/no-imm32
21516     0/imm32/no-imm8
21517     0/imm32/no-disp32
21518     0/imm32/no-xm32
21519     0/imm32/no-x32
21520     0x11/imm32/alloc-id:fake
21521     _Primitive-decrement-edx/imm32/next
21522 _Primitive-decrement-edx:  # (payload primitive)
21523     0x11/imm32/alloc-id:fake:payload
21524     # var/edx <- decrement => 4a/decrement-edx
21525     0x11/imm32/alloc-id:fake
21526     _string-decrement/imm32/name
21527     0/imm32/no-inouts
21528     0/imm32/no-inouts
21529     0x11/imm32/alloc-id:fake
21530     Single-int-var-in-edx/imm32/outputs
21531     0x11/imm32/alloc-id:fake
21532     _string_4a_decrement_edx/imm32/subx-name
21533     0/imm32/no-rm32
21534     0/imm32/no-r32
21535     0/imm32/no-imm32
21536     0/imm32/no-imm8
21537     0/imm32/no-disp32
21538     0/imm32/no-xm32
21539     0/imm32/no-x32
21540     0x11/imm32/alloc-id:fake
21541     _Primitive-decrement-ebx/imm32/next
21542 _Primitive-decrement-ebx:  # (payload primitive)
21543     0x11/imm32/alloc-id:fake:payload
21544     # var/ebx <- decrement => 4b/decrement-ebx
21545     0x11/imm32/alloc-id:fake
21546     _string-decrement/imm32/name
21547     0/imm32/no-inouts
21548     0/imm32/no-inouts
21549     0x11/imm32/alloc-id:fake
21550     Single-int-var-in-ebx/imm32/outputs
21551     0x11/imm32/alloc-id:fake
21552     _string_4b_decrement_ebx/imm32/subx-name
21553     0/imm32/no-rm32
21554     0/imm32/no-r32
21555     0/imm32/no-imm32
21556     0/imm32/no-imm8
21557     0/imm32/no-disp32
21558     0/imm32/no-xm32
21559     0/imm32/no-x32
21560     0x11/imm32/alloc-id:fake
21561     _Primitive-decrement-esi/imm32/next
21562 _Primitive-decrement-esi:  # (payload primitive)
21563     0x11/imm32/alloc-id:fake:payload
21564     # var/esi <- decrement => 4e/decrement-esi
21565     0x11/imm32/alloc-id:fake
21566     _string-decrement/imm32/name
21567     0/imm32/no-inouts
21568     0/imm32/no-inouts
21569     0x11/imm32/alloc-id:fake
21570     Single-int-var-in-esi/imm32/outputs
21571     0x11/imm32/alloc-id:fake
21572     _string_4e_decrement_esi/imm32/subx-name
21573     0/imm32/no-rm32
21574     0/imm32/no-r32
21575     0/imm32/no-imm32
21576     0/imm32/no-imm8
21577     0/imm32/no-disp32
21578     0/imm32/no-xm32
21579     0/imm32/no-x32
21580     0x11/imm32/alloc-id:fake
21581     _Primitive-decrement-edi/imm32/next
21582 _Primitive-decrement-edi:  # (payload primitive)
21583     0x11/imm32/alloc-id:fake:payload
21584     # var/edi <- decrement => 4f/decrement-edi
21585     0x11/imm32/alloc-id:fake
21586     _string-decrement/imm32/name
21587     0/imm32/no-inouts
21588     0/imm32/no-inouts
21589     0x11/imm32/alloc-id:fake
21590     Single-int-var-in-edi/imm32/outputs
21591     0x11/imm32/alloc-id:fake
21592     _string_4f_decrement_edi/imm32/subx-name
21593     0/imm32/no-rm32
21594     0/imm32/no-r32
21595     0/imm32/no-imm32
21596     0/imm32/no-imm8
21597     0/imm32/no-disp32
21598     0/imm32/no-xm32
21599     0/imm32/no-x32
21600     0x11/imm32/alloc-id:fake
21601     _Primitive-increment-mem/imm32/next
21602 _Primitive-increment-mem:  # (payload primitive)
21603     0x11/imm32/alloc-id:fake:payload
21604     # increment var => ff 0/subop/increment *(ebp+__)
21605     0x11/imm32/alloc-id:fake
21606     _string-increment/imm32/name
21607     0x11/imm32/alloc-id:fake
21608     Single-int-var-in-mem/imm32/inouts
21609     0/imm32/no-outputs
21610     0/imm32/no-outputs
21611     0x11/imm32/alloc-id:fake
21612     _string_ff_subop_increment/imm32/subx-name
21613     1/imm32/rm32-is-first-inout
21614     0/imm32/no-r32
21615     0/imm32/no-imm32
21616     0/imm32/no-imm8
21617     0/imm32/no-disp32
21618     0/imm32/no-xm32
21619     0/imm32/no-x32
21620     0x11/imm32/alloc-id:fake
21621     _Primitive-increment-reg/imm32/next
21622 _Primitive-increment-reg:  # (payload primitive)
21623     0x11/imm32/alloc-id:fake:payload
21624     # var/reg <- increment => ff 0/subop/increment %__
21625     0x11/imm32/alloc-id:fake
21626     _string-increment/imm32/name
21627     0/imm32/no-inouts
21628     0/imm32/no-inouts
21629     0x11/imm32/alloc-id:fake
21630     Single-int-var-in-some-register/imm32/outputs
21631     0x11/imm32/alloc-id:fake
21632     _string_ff_subop_increment/imm32/subx-name
21633     3/imm32/rm32-is-first-output
21634     0/imm32/no-r32
21635     0/imm32/no-imm32
21636     0/imm32/no-imm8
21637     0/imm32/no-disp32
21638     0/imm32/no-xm32
21639     0/imm32/no-x32
21640     0x11/imm32/alloc-id:fake
21641     _Primitive-decrement-mem/imm32/next
21642 _Primitive-decrement-mem:  # (payload primitive)
21643     0x11/imm32/alloc-id:fake:payload
21644     # decrement var => ff 1/subop/decrement *(ebp+__)
21645     0x11/imm32/alloc-id:fake
21646     _string-decrement/imm32/name
21647     0x11/imm32/alloc-id:fake
21648     Single-int-var-in-mem/imm32/inouts
21649     0/imm32/no-outputs
21650     0/imm32/no-outputs
21651     0x11/imm32/alloc-id:fake
21652     _string_ff_subop_decrement/imm32/subx-name
21653     1/imm32/rm32-is-first-inout
21654     0/imm32/no-r32
21655     0/imm32/no-imm32
21656     0/imm32/no-imm8
21657     0/imm32/no-disp32
21658     0/imm32/no-xm32
21659     0/imm32/no-x32
21660     0x11/imm32/alloc-id:fake
21661     _Primitive-decrement-reg/imm32/next
21662 _Primitive-decrement-reg:  # (payload primitive)
21663     0x11/imm32/alloc-id:fake:payload
21664     # var/reg <- decrement => ff 1/subop/decrement %__
21665     0x11/imm32/alloc-id:fake
21666     _string-decrement/imm32/name
21667     0/imm32/no-inouts
21668     0/imm32/no-inouts
21669     0x11/imm32/alloc-id:fake
21670     Single-int-var-in-some-register/imm32/outputs
21671     0x11/imm32/alloc-id:fake
21672     _string_ff_subop_decrement/imm32/subx-name
21673     3/imm32/rm32-is-first-output
21674     0/imm32/no-r32
21675     0/imm32/no-imm32
21676     0/imm32/no-imm8
21677     0/imm32/no-disp32
21678     0/imm32/no-xm32
21679     0/imm32/no-x32
21680     0x11/imm32/alloc-id:fake
21681     _Primitive-add-to-eax/imm32/next
21682 # - add
21683 _Primitive-add-to-eax:  # (payload primitive)
21684     0x11/imm32/alloc-id:fake:payload
21685     # var/eax <- add lit => 05/add-to-eax lit/imm32
21686     0x11/imm32/alloc-id:fake
21687     _string-add/imm32/name
21688     0x11/imm32/alloc-id:fake
21689     Single-lit-var/imm32/inouts
21690     0x11/imm32/alloc-id:fake
21691     Single-int-var-in-eax/imm32/outputs
21692     0x11/imm32/alloc-id:fake
21693     _string_05_add_to_eax/imm32/subx-name
21694     0/imm32/no-rm32
21695     0/imm32/no-r32
21696     1/imm32/imm32-is-first-inout
21697     0/imm32/no-imm8
21698     0/imm32/no-disp32
21699     0/imm32/no-xm32
21700     0/imm32/no-x32
21701     0x11/imm32/alloc-id:fake
21702     _Primitive-add-reg-to-reg/imm32/next
21703 _Primitive-add-reg-to-reg:  # (payload primitive)
21704     0x11/imm32/alloc-id:fake:payload
21705     # var1/reg <- add var2/reg => 01/add-to var1/rm32 var2/r32
21706     0x11/imm32/alloc-id:fake
21707     _string-add/imm32/name
21708     0x11/imm32/alloc-id:fake
21709     Single-int-var-in-some-register/imm32/inouts
21710     0x11/imm32/alloc-id:fake
21711     Single-int-var-in-some-register/imm32/outputs
21712     0x11/imm32/alloc-id:fake
21713     _string_01_add_to/imm32/subx-name
21714     3/imm32/rm32-is-first-output
21715     1/imm32/r32-is-first-inout
21716     0/imm32/no-imm32
21717     0/imm32/no-imm8
21718     0/imm32/no-disp32
21719     0/imm32/no-xm32
21720     0/imm32/no-x32
21721     0x11/imm32/alloc-id:fake
21722     _Primitive-add-reg-to-mem/imm32/next
21723 _Primitive-add-reg-to-mem:  # (payload primitive)
21724     0x11/imm32/alloc-id:fake:payload
21725     # add-to var1 var2/reg => 01/add-to var1 var2/r32
21726     0x11/imm32/alloc-id:fake
21727     _string-add-to/imm32/name
21728     0x11/imm32/alloc-id:fake
21729     Two-args-int-stack-int-reg/imm32/inouts
21730     0/imm32/no-outputs
21731     0/imm32/no-outputs
21732     0x11/imm32/alloc-id:fake
21733     _string_01_add_to/imm32/subx-name
21734     1/imm32/rm32-is-first-inout
21735     2/imm32/r32-is-second-inout
21736     0/imm32/no-imm32
21737     0/imm32/no-imm8
21738     0/imm32/no-disp32
21739     0/imm32/no-xm32
21740     0/imm32/no-x32
21741     0x11/imm32/alloc-id:fake
21742     _Primitive-add-mem-to-reg/imm32/next
21743 _Primitive-add-mem-to-reg:  # (payload primitive)
21744     0x11/imm32/alloc-id:fake:payload
21745     # var1/reg <- add var2 => 03/add var2/rm32 var1/r32
21746     0x11/imm32/alloc-id:fake
21747     _string-add/imm32/name
21748     0x11/imm32/alloc-id:fake
21749     Single-int-var-in-mem/imm32/inouts
21750     0x11/imm32/alloc-id:fake
21751     Single-int-var-in-some-register/imm32/outputs
21752     0x11/imm32/alloc-id:fake
21753     _string_03_add/imm32/subx-name
21754     1/imm32/rm32-is-first-inout
21755     3/imm32/r32-is-first-output
21756     0/imm32/no-imm32
21757     0/imm32/no-imm8
21758     0/imm32/no-disp32
21759     0/imm32/no-xm32
21760     0/imm32/no-x32
21761     0x11/imm32/alloc-id:fake
21762     _Primitive-add-lit-to-reg/imm32/next
21763 _Primitive-add-lit-to-reg:  # (payload primitive)
21764     0x11/imm32/alloc-id:fake:payload
21765     # var1/reg <- add lit => 81 0/subop/add var1/rm32 lit/imm32
21766     0x11/imm32/alloc-id:fake
21767     _string-add/imm32/name
21768     0x11/imm32/alloc-id:fake
21769     Single-lit-var/imm32/inouts
21770     0x11/imm32/alloc-id:fake
21771     Single-int-var-in-some-register/imm32/outputs
21772     0x11/imm32/alloc-id:fake
21773     _string_81_subop_add/imm32/subx-name
21774     3/imm32/rm32-is-first-output
21775     0/imm32/no-r32
21776     1/imm32/imm32-is-first-inout
21777     0/imm32/no-imm8
21778     0/imm32/no-disp32
21779     0/imm32/no-xm32
21780     0/imm32/no-x32
21781     0x11/imm32/alloc-id:fake
21782     _Primitive-add-lit-to-mem/imm32/next
21783 _Primitive-add-lit-to-mem:  # (payload primitive)
21784     0x11/imm32/alloc-id:fake:payload
21785     # add-to var1, lit => 81 0/subop/add var1/rm32 lit/imm32
21786     0x11/imm32/alloc-id:fake
21787     _string-add-to/imm32/name
21788     0x11/imm32/alloc-id:fake
21789     Int-var-and-literal/imm32/inouts
21790     0/imm32/no-outputs
21791     0/imm32/no-outputs
21792     0x11/imm32/alloc-id:fake
21793     _string_81_subop_add/imm32/subx-name
21794     1/imm32/rm32-is-first-inout
21795     0/imm32/no-r32
21796     2/imm32/imm32-is-second-inout
21797     0/imm32/no-imm8
21798     0/imm32/no-disp32
21799     0/imm32/no-xm32
21800     0/imm32/no-x32
21801     0x11/imm32/alloc-id:fake
21802     _Primitive-subtract-from-eax/imm32/next
21803 # - subtract
21804 _Primitive-subtract-from-eax:  # (payload primitive)
21805     0x11/imm32/alloc-id:fake:payload
21806     # var/eax <- subtract lit => 2d/subtract-from-eax lit/imm32
21807     0x11/imm32/alloc-id:fake
21808     _string-subtract/imm32/name
21809     0x11/imm32/alloc-id:fake
21810     Single-lit-var/imm32/inouts
21811     0x11/imm32/alloc-id:fake
21812     Single-int-var-in-eax/imm32/outputs
21813     0x11/imm32/alloc-id:fake
21814     _string_2d_subtract_from_eax/imm32/subx-name
21815     0/imm32/no-rm32
21816     0/imm32/no-r32
21817     1/imm32/imm32-is-first-inout
21818     0/imm32/no-imm8
21819     0/imm32/no-disp32
21820     0/imm32/no-xm32
21821     0/imm32/no-x32
21822     0x11/imm32/alloc-id:fake
21823     _Primitive-subtract-reg-from-reg/imm32/next
21824 _Primitive-subtract-reg-from-reg:  # (payload primitive)
21825     0x11/imm32/alloc-id:fake:payload
21826     # var1/reg <- subtract var2/reg => 29/subtract-from var1/rm32 var2/r32
21827     0x11/imm32/alloc-id:fake
21828     _string-subtract/imm32/name
21829     0x11/imm32/alloc-id:fake
21830     Single-int-var-in-some-register/imm32/inouts
21831     0x11/imm32/alloc-id:fake
21832     Single-int-var-in-some-register/imm32/outputs
21833     0x11/imm32/alloc-id:fake
21834     _string_29_subtract_from/imm32/subx-name
21835     3/imm32/rm32-is-first-output
21836     1/imm32/r32-is-first-inout
21837     0/imm32/no-imm32
21838     0/imm32/no-imm8
21839     0/imm32/no-disp32
21840     0/imm32/no-xm32
21841     0/imm32/no-x32
21842     0x11/imm32/alloc-id:fake
21843     _Primitive-subtract-reg-from-mem/imm32/next
21844 _Primitive-subtract-reg-from-mem:  # (payload primitive)
21845     0x11/imm32/alloc-id:fake:payload
21846     # subtract-from var1 var2/reg => 29/subtract-from var1 var2/r32
21847     0x11/imm32/alloc-id:fake
21848     _string-subtract-from/imm32/name
21849     0x11/imm32/alloc-id:fake
21850     Two-args-int-stack-int-reg/imm32/inouts
21851     0/imm32/no-outputs
21852     0/imm32/no-outputs
21853     0x11/imm32/alloc-id:fake
21854     _string_29_subtract_from/imm32/subx-name
21855     1/imm32/rm32-is-first-inout
21856     2/imm32/r32-is-second-inout
21857     0/imm32/no-imm32
21858     0/imm32/no-imm8
21859     0/imm32/no-disp32
21860     0/imm32/no-xm32
21861     0/imm32/no-x32
21862     0x11/imm32/alloc-id:fake
21863     _Primitive-subtract-mem-from-reg/imm32/next
21864 _Primitive-subtract-mem-from-reg:  # (payload primitive)
21865     0x11/imm32/alloc-id:fake:payload
21866     # var1/reg <- subtract var2 => 2b/subtract var2/rm32 var1/r32
21867     0x11/imm32/alloc-id:fake
21868     _string-subtract/imm32/name
21869     0x11/imm32/alloc-id:fake
21870     Single-int-var-in-mem/imm32/inouts
21871     0x11/imm32/alloc-id:fake
21872     Single-int-var-in-some-register/imm32/outputs
21873     0x11/imm32/alloc-id:fake
21874     _string_2b_subtract/imm32/subx-name
21875     1/imm32/rm32-is-first-inout
21876     3/imm32/r32-is-first-output
21877     0/imm32/no-imm32
21878     0/imm32/no-imm8
21879     0/imm32/no-disp32
21880     0/imm32/no-xm32
21881     0/imm32/no-x32
21882     0x11/imm32/alloc-id:fake
21883     _Primitive-subtract-lit-from-reg/imm32/next
21884 _Primitive-subtract-lit-from-reg:  # (payload primitive)
21885     0x11/imm32/alloc-id:fake:payload
21886     # var1/reg <- subtract lit => 81 5/subop/subtract var1/rm32 lit/imm32
21887     0x11/imm32/alloc-id:fake
21888     _string-subtract/imm32/name
21889     0x11/imm32/alloc-id:fake
21890     Single-lit-var/imm32/inouts
21891     0x11/imm32/alloc-id:fake
21892     Single-int-var-in-some-register/imm32/outputs
21893     0x11/imm32/alloc-id:fake
21894     _string_81_subop_subtract/imm32/subx-name
21895     3/imm32/rm32-is-first-output
21896     0/imm32/no-r32
21897     1/imm32/imm32-is-first-inout
21898     0/imm32/no-imm8
21899     0/imm32/no-disp32
21900     0/imm32/no-xm32
21901     0/imm32/no-x32
21902     0x11/imm32/alloc-id:fake
21903     _Primitive-subtract-lit-from-mem/imm32/next
21904 _Primitive-subtract-lit-from-mem:  # (payload primitive)
21905     0x11/imm32/alloc-id:fake:payload
21906     # subtract-from var1, lit => 81 5/subop/subtract var1/rm32 lit/imm32
21907     0x11/imm32/alloc-id:fake
21908     _string-subtract-from/imm32/name
21909     0x11/imm32/alloc-id:fake
21910     Int-var-and-literal/imm32/inouts
21911     0/imm32/no-outputs
21912     0/imm32/no-outputs
21913     0x11/imm32/alloc-id:fake
21914     _string_81_subop_subtract/imm32/subx-name
21915     1/imm32/rm32-is-first-inout
21916     0/imm32/no-r32
21917     2/imm32/imm32-is-second-inout
21918     0/imm32/no-imm8
21919     0/imm32/no-disp32
21920     0/imm32/no-xm32
21921     0/imm32/no-x32
21922     0x11/imm32/alloc-id:fake
21923     _Primitive-and-with-eax/imm32/next
21924 # - and
21925 _Primitive-and-with-eax:  # (payload primitive)
21926     0x11/imm32/alloc-id:fake:payload
21927     # var/eax <- and lit => 25/and-with-eax lit/imm32
21928     0x11/imm32/alloc-id:fake
21929     _string-and/imm32/name
21930     0x11/imm32/alloc-id:fake
21931     Single-lit-var/imm32/inouts
21932     0x11/imm32/alloc-id:fake
21933     Single-int-var-in-eax/imm32/outputs
21934     0x11/imm32/alloc-id:fake
21935     _string_25_and_with_eax/imm32/subx-name
21936     0/imm32/no-rm32
21937     0/imm32/no-r32
21938     1/imm32/imm32-is-first-inout
21939     0/imm32/no-imm8
21940     0/imm32/no-disp32
21941     0/imm32/no-xm32
21942     0/imm32/no-x32
21943     0x11/imm32/alloc-id:fake
21944     _Primitive-and-reg-with-reg/imm32/next
21945 _Primitive-and-reg-with-reg:  # (payload primitive)
21946     0x11/imm32/alloc-id:fake:payload
21947     # var1/reg <- and var2/reg => 21/and-with var1/rm32 var2/r32
21948     0x11/imm32/alloc-id:fake
21949     _string-and/imm32/name
21950     0x11/imm32/alloc-id:fake
21951     Single-int-var-in-some-register/imm32/inouts
21952     0x11/imm32/alloc-id:fake
21953     Single-int-var-in-some-register/imm32/outputs
21954     0x11/imm32/alloc-id:fake
21955     _string_21_and_with/imm32/subx-name
21956     3/imm32/rm32-is-first-output
21957     1/imm32/r32-is-first-inout
21958     0/imm32/no-imm32
21959     0/imm32/no-imm8
21960     0/imm32/no-disp32
21961     0/imm32/no-xm32
21962     0/imm32/no-x32
21963     0x11/imm32/alloc-id:fake
21964     _Primitive-and-reg-with-mem/imm32/next
21965 _Primitive-and-reg-with-mem:  # (payload primitive)
21966     0x11/imm32/alloc-id:fake:payload
21967     # and-with var1 var2/reg => 21/and-with var1 var2/r32
21968     0x11/imm32/alloc-id:fake
21969     _string-and-with/imm32/name
21970     0x11/imm32/alloc-id:fake
21971     Two-args-int-stack-int-reg/imm32/inouts
21972     0/imm32/no-outputs
21973     0/imm32/no-outputs
21974     0x11/imm32/alloc-id:fake
21975     _string_21_and_with/imm32/subx-name
21976     1/imm32/rm32-is-first-inout
21977     2/imm32/r32-is-second-inout
21978     0/imm32/no-imm32
21979     0/imm32/no-imm8
21980     0/imm32/no-disp32
21981     0/imm32/no-xm32
21982     0/imm32/no-x32
21983     0x11/imm32/alloc-id:fake
21984     _Primitive-and-mem-with-reg/imm32/next
21985 _Primitive-and-mem-with-reg:  # (payload primitive)
21986     0x11/imm32/alloc-id:fake:payload
21987     # var1/reg <- and var2 => 23/and var2/rm32 var1/r32
21988     0x11/imm32/alloc-id:fake
21989     _string-and/imm32/name
21990     0x11/imm32/alloc-id:fake
21991     Single-int-var-in-mem/imm32/inouts
21992     0x11/imm32/alloc-id:fake
21993     Single-int-var-in-some-register/imm32/outputs
21994     0x11/imm32/alloc-id:fake
21995     _string_23_and/imm32/subx-name
21996     1/imm32/rm32-is-first-inout
21997     3/imm32/r32-is-first-output
21998     0/imm32/no-imm32
21999     0/imm32/no-imm8
22000     0/imm32/no-disp32
22001     0/imm32/no-xm32
22002     0/imm32/no-x32
22003     0x11/imm32/alloc-id:fake
22004     _Primitive-and-lit-with-reg/imm32/next
22005 _Primitive-and-lit-with-reg:  # (payload primitive)
22006     0x11/imm32/alloc-id:fake:payload
22007     # var1/reg <- and lit => 81 4/subop/and var1/rm32 lit/imm32
22008     0x11/imm32/alloc-id:fake
22009     _string-and/imm32/name
22010     0x11/imm32/alloc-id:fake
22011     Single-lit-var/imm32/inouts
22012     0x11/imm32/alloc-id:fake
22013     Single-int-var-in-some-register/imm32/outputs
22014     0x11/imm32/alloc-id:fake
22015     _string_81_subop_and/imm32/subx-name
22016     3/imm32/rm32-is-first-output
22017     0/imm32/no-r32
22018     1/imm32/imm32-is-first-inout
22019     0/imm32/no-imm8
22020     0/imm32/no-disp32
22021     0/imm32/no-xm32
22022     0/imm32/no-x32
22023     0x11/imm32/alloc-id:fake
22024     _Primitive-and-lit-with-mem/imm32/next
22025 _Primitive-and-lit-with-mem:  # (payload primitive)
22026     0x11/imm32/alloc-id:fake:payload
22027     # and-with var1, lit => 81 4/subop/and var1/rm32 lit/imm32
22028     0x11/imm32/alloc-id:fake
22029     _string-and-with/imm32/name
22030     0x11/imm32/alloc-id:fake
22031     Int-var-and-literal/imm32/inouts
22032     0/imm32/no-outputs
22033     0/imm32/no-outputs
22034     0x11/imm32/alloc-id:fake
22035     _string_81_subop_and/imm32/subx-name
22036     1/imm32/rm32-is-first-inout
22037     0/imm32/no-r32
22038     2/imm32/imm32-is-second-inout
22039     0/imm32/no-imm8
22040     0/imm32/no-disp32
22041     0/imm32/no-xm32
22042     0/imm32/no-x32
22043     0x11/imm32/alloc-id:fake
22044     _Primitive-or-with-eax/imm32/next
22045 # - or
22046 _Primitive-or-with-eax:  # (payload primitive)
22047     0x11/imm32/alloc-id:fake:payload
22048     # var/eax <- or lit => 0d/or-with-eax lit/imm32
22049     0x11/imm32/alloc-id:fake
22050     _string-or/imm32/name
22051     0x11/imm32/alloc-id:fake
22052     Single-lit-var/imm32/inouts
22053     0x11/imm32/alloc-id:fake
22054     Single-int-var-in-eax/imm32/outputs
22055     0x11/imm32/alloc-id:fake
22056     _string_0d_or_with_eax/imm32/subx-name
22057     0/imm32/no-rm32
22058     0/imm32/no-r32
22059     1/imm32/imm32-is-first-inout
22060     0/imm32/no-imm8
22061     0/imm32/no-disp32
22062     0/imm32/no-xm32
22063     0/imm32/no-x32
22064     0x11/imm32/alloc-id:fake
22065     _Primitive-or-reg-with-reg/imm32/next
22066 _Primitive-or-reg-with-reg:  # (payload primitive)
22067     0x11/imm32/alloc-id:fake:payload
22068     # var1/reg <- or var2/reg => 09/or-with var1/rm32 var2/r32
22069     0x11/imm32/alloc-id:fake
22070     _string-or/imm32/name
22071     0x11/imm32/alloc-id:fake
22072     Single-int-var-in-some-register/imm32/inouts
22073     0x11/imm32/alloc-id:fake
22074     Single-int-var-in-some-register/imm32/outputs
22075     0x11/imm32/alloc-id:fake
22076     _string_09_or_with/imm32/subx-name
22077     3/imm32/rm32-is-first-output
22078     1/imm32/r32-is-first-inout
22079     0/imm32/no-imm32
22080     0/imm32/no-imm8
22081     0/imm32/no-disp32
22082     0/imm32/no-xm32
22083     0/imm32/no-x32
22084     0x11/imm32/alloc-id:fake
22085     _Primitive-or-reg-with-mem/imm32/next
22086 _Primitive-or-reg-with-mem:  # (payload primitive)
22087     0x11/imm32/alloc-id:fake:payload
22088     # or-with var1 var2/reg => 09/or-with var1 var2/r32
22089     0x11/imm32/alloc-id:fake
22090     _string-or-with/imm32/name
22091     0x11/imm32/alloc-id:fake
22092     Two-args-int-stack-int-reg/imm32/inouts
22093     0/imm32/no-outputs
22094     0/imm32/no-outputs
22095     0x11/imm32/alloc-id:fake
22096     _string_09_or_with/imm32/subx-name
22097     1/imm32/rm32-is-first-inout
22098     2/imm32/r32-is-second-inout
22099     0/imm32/no-imm32
22100     0/imm32/no-imm8
22101     0/imm32/no-disp32
22102     0/imm32/no-xm32
22103     0/imm32/no-x32
22104     0x11/imm32/alloc-id:fake
22105     _Primitive-or-mem-with-reg/imm32/next
22106 _Primitive-or-mem-with-reg:  # (payload primitive)
22107     0x11/imm32/alloc-id:fake:payload
22108     # var1/reg <- or var2 => 0b/or var2/rm32 var1/r32
22109     0x11/imm32/alloc-id:fake
22110     _string-or/imm32/name
22111     0x11/imm32/alloc-id:fake
22112     Single-int-var-in-mem/imm32/inouts
22113     0x11/imm32/alloc-id:fake
22114     Single-int-var-in-some-register/imm32/outputs
22115     0x11/imm32/alloc-id:fake
22116     _string_0b_or/imm32/subx-name
22117     1/imm32/rm32-is-first-inout
22118     3/imm32/r32-is-first-output
22119     0/imm32/no-imm32
22120     0/imm32/no-imm8
22121     0/imm32/no-disp32
22122     0/imm32/no-xm32
22123     0/imm32/no-x32
22124     0x11/imm32/alloc-id:fake
22125     _Primitive-or-lit-with-reg/imm32/next
22126 _Primitive-or-lit-with-reg:  # (payload primitive)
22127     0x11/imm32/alloc-id:fake:payload
22128     # var1/reg <- or lit => 81 1/subop/or var1/rm32 lit/imm32
22129     0x11/imm32/alloc-id:fake
22130     _string-or/imm32/name
22131     0x11/imm32/alloc-id:fake
22132     Single-lit-var/imm32/inouts
22133     0x11/imm32/alloc-id:fake
22134     Single-int-var-in-some-register/imm32/outputs
22135     0x11/imm32/alloc-id:fake
22136     _string_81_subop_or/imm32/subx-name
22137     3/imm32/rm32-is-first-output
22138     0/imm32/no-r32
22139     1/imm32/imm32-is-first-inout
22140     0/imm32/no-imm8
22141     0/imm32/no-disp32
22142     0/imm32/no-xm32
22143     0/imm32/no-x32
22144     0x11/imm32/alloc-id:fake
22145     _Primitive-or-lit-with-mem/imm32/next
22146 _Primitive-or-lit-with-mem:  # (payload primitive)
22147     0x11/imm32/alloc-id:fake:payload
22148     # or-with var1, lit => 81 1/subop/or var1/rm32 lit/imm32
22149     0x11/imm32/alloc-id:fake
22150     _string-or-with/imm32/name
22151     0x11/imm32/alloc-id:fake
22152     Int-var-and-literal/imm32/inouts
22153     0/imm32/no-outputs
22154     0/imm32/no-outputs
22155     0x11/imm32/alloc-id:fake
22156     _string_81_subop_or/imm32/subx-name
22157     1/imm32/rm32-is-first-inout
22158     0/imm32/no-r32
22159     2/imm32/imm32-is-second-inout
22160     0/imm32/no-imm8
22161     0/imm32/no-disp32
22162     0/imm32/no-xm32
22163     0/imm32/no-x32
22164     0x11/imm32/alloc-id:fake
22165     _Primitive-xor-with-eax/imm32/next
22166 # - xor
22167 _Primitive-xor-with-eax:  # (payload primitive)
22168     0x11/imm32/alloc-id:fake:payload
22169     # var/eax <- xor lit => 35/xor-with-eax lit/imm32
22170     0x11/imm32/alloc-id:fake
22171     _string-xor/imm32/name
22172     0x11/imm32/alloc-id:fake
22173     Single-lit-var/imm32/inouts
22174     0x11/imm32/alloc-id:fake
22175     Single-int-var-in-eax/imm32/outputs
22176     0x11/imm32/alloc-id:fake
22177     _string_35_xor_with_eax/imm32/subx-name
22178     0/imm32/no-rm32
22179     0/imm32/no-r32
22180     1/imm32/imm32-is-first-inout
22181     0/imm32/no-imm8
22182     0/imm32/no-disp32
22183     0/imm32/no-xm32
22184     0/imm32/no-x32
22185     0x11/imm32/alloc-id:fake
22186     _Primitive-xor-reg-with-reg/imm32/next
22187 _Primitive-xor-reg-with-reg:  # (payload primitive)
22188     0x11/imm32/alloc-id:fake:payload
22189     # var1/reg <- xor var2/reg => 31/xor-with var1/rm32 var2/r32
22190     0x11/imm32/alloc-id:fake
22191     _string-xor/imm32/name
22192     0x11/imm32/alloc-id:fake
22193     Single-int-var-in-some-register/imm32/inouts
22194     0x11/imm32/alloc-id:fake
22195     Single-int-var-in-some-register/imm32/outputs
22196     0x11/imm32/alloc-id:fake
22197     _string_31_xor_with/imm32/subx-name
22198     3/imm32/rm32-is-first-output
22199     1/imm32/r32-is-first-inout
22200     0/imm32/no-imm32
22201     0/imm32/no-imm8
22202     0/imm32/no-disp32
22203     0/imm32/no-xm32
22204     0/imm32/no-x32
22205     0x11/imm32/alloc-id:fake
22206     _Primitive-xor-reg-with-mem/imm32/next
22207 _Primitive-xor-reg-with-mem:  # (payload primitive)
22208     0x11/imm32/alloc-id:fake:payload
22209     # xor-with var1 var2/reg => 31/xor-with var1 var2/r32
22210     0x11/imm32/alloc-id:fake
22211     _string-xor-with/imm32/name
22212     0x11/imm32/alloc-id:fake
22213     Two-args-int-stack-int-reg/imm32/inouts
22214     0/imm32/no-outputs
22215     0/imm32/no-outputs
22216     0x11/imm32/alloc-id:fake
22217     _string_31_xor_with/imm32/subx-name
22218     1/imm32/rm32-is-first-inout
22219     2/imm32/r32-is-second-inout
22220     0/imm32/no-imm32
22221     0/imm32/no-imm8
22222     0/imm32/no-disp32
22223     0/imm32/no-xm32
22224     0/imm32/no-x32
22225     0x11/imm32/alloc-id:fake
22226     _Primitive-xor-mem-with-reg/imm32/next
22227 _Primitive-xor-mem-with-reg:  # (payload primitive)
22228     0x11/imm32/alloc-id:fake:payload
22229     # var1/reg <- xor var2 => 33/xor var2/rm32 var1/r32
22230     0x11/imm32/alloc-id:fake
22231     _string-xor/imm32/name
22232     0x11/imm32/alloc-id:fake
22233     Single-int-var-in-mem/imm32/inouts
22234     0x11/imm32/alloc-id:fake
22235     Single-int-var-in-some-register/imm32/outputs
22236     0x11/imm32/alloc-id:fake
22237     _string_33_xor/imm32/subx-name
22238     1/imm32/rm32-is-first-inout
22239     3/imm32/r32-is-first-output
22240     0/imm32/no-imm32
22241     0/imm32/no-imm8
22242     0/imm32/no-disp32
22243     0/imm32/no-xm32
22244     0/imm32/no-x32
22245     0x11/imm32/alloc-id:fake
22246     _Primitive-xor-lit-with-reg/imm32/next
22247 _Primitive-xor-lit-with-reg:  # (payload primitive)
22248     0x11/imm32/alloc-id:fake:payload
22249     # var1/reg <- xor lit => 81 6/subop/xor var1/rm32 lit/imm32
22250     0x11/imm32/alloc-id:fake
22251     _string-xor/imm32/name
22252     0x11/imm32/alloc-id:fake
22253     Single-lit-var/imm32/inouts
22254     0x11/imm32/alloc-id:fake
22255     Single-int-var-in-some-register/imm32/outputs
22256     0x11/imm32/alloc-id:fake
22257     _string_81_subop_xor/imm32/subx-name
22258     3/imm32/rm32-is-first-output
22259     0/imm32/no-r32
22260     1/imm32/imm32-is-first-inout
22261     0/imm32/no-imm8
22262     0/imm32/no-disp32
22263     0/imm32/no-xm32
22264     0/imm32/no-x32
22265     0x11/imm32/alloc-id:fake
22266     _Primitive-xor-lit-with-mem/imm32/next
22267 _Primitive-xor-lit-with-mem:  # (payload primitive)
22268     0x11/imm32/alloc-id:fake:payload
22269     # xor-with var1, lit => 81 6/subop/xor var1/rm32 lit/imm32
22270     0x11/imm32/alloc-id:fake
22271     _string-xor-with/imm32/name
22272     0x11/imm32/alloc-id:fake
22273     Int-var-and-literal/imm32/inouts
22274     0/imm32/no-outputs
22275     0/imm32/no-outputs
22276     0x11/imm32/alloc-id:fake
22277     _string_81_subop_xor/imm32/subx-name
22278     1/imm32/rm32-is-first-inout
22279     0/imm32/no-r32
22280     2/imm32/imm32-is-second-inout
22281     0/imm32/no-imm8
22282     0/imm32/no-disp32
22283     0/imm32/no-xm32
22284     0/imm32/no-x32
22285     0x11/imm32/alloc-id:fake
22286     _Primitive-shift-reg-left-by-lit/imm32/next
22287 _Primitive-shift-reg-left-by-lit:  # (payload primitive)
22288     0x11/imm32/alloc-id:fake:payload
22289     # var1/reg <- shift-left lit => c1/shift 4/subop/left var1/rm32 lit/imm32
22290     0x11/imm32/alloc-id:fake
22291     _string-shift-left/imm32/name
22292     0x11/imm32/alloc-id:fake
22293     Single-lit-var/imm32/inouts
22294     0x11/imm32/alloc-id:fake
22295     Single-int-var-in-some-register/imm32/outputs
22296     0x11/imm32/alloc-id:fake
22297     _string_c1_subop_shift_left/imm32/subx-name
22298     3/imm32/rm32-is-first-output
22299     0/imm32/no-r32
22300     0/imm32/no-imm32
22301     1/imm32/imm8-is-first-inout
22302     0/imm32/no-disp32
22303     0/imm32/no-xm32
22304     0/imm32/no-x32
22305     0x11/imm32/alloc-id:fake
22306     _Primitive-shift-reg-right-by-lit/imm32/next
22307 _Primitive-shift-reg-right-by-lit:  # (payload primitive)
22308     0x11/imm32/alloc-id:fake:payload
22309     # var1/reg <- shift-right lit => c1/shift 5/subop/right var1/rm32 lit/imm32
22310     0x11/imm32/alloc-id:fake
22311     _string-shift-right/imm32/name
22312     0x11/imm32/alloc-id:fake
22313     Single-lit-var/imm32/inouts
22314     0x11/imm32/alloc-id:fake
22315     Single-int-var-in-some-register/imm32/outputs
22316     0x11/imm32/alloc-id:fake
22317     _string_c1_subop_shift_right_padding_zeroes/imm32/subx-name
22318     3/imm32/rm32-is-first-output
22319     0/imm32/no-r32
22320     0/imm32/no-imm32
22321     1/imm32/imm8-is-first-inout
22322     0/imm32/no-disp32
22323     0/imm32/no-xm32
22324     0/imm32/no-x32
22325     0x11/imm32/alloc-id:fake
22326     _Primitive-shift-reg-right-signed-by-lit/imm32/next
22327 _Primitive-shift-reg-right-signed-by-lit:  # (payload primitive)
22328     0x11/imm32/alloc-id:fake:payload
22329     # var1/reg <- shift-right-signed lit => c1/shift 7/subop/right-preserving-sign var1/rm32 lit/imm32
22330     0x11/imm32/alloc-id:fake
22331     _string-shift-right-signed/imm32/name
22332     0x11/imm32/alloc-id:fake
22333     Single-lit-var/imm32/inouts
22334     0x11/imm32/alloc-id:fake
22335     Single-int-var-in-some-register/imm32/outputs
22336     0x11/imm32/alloc-id:fake
22337     _string_c1_subop_shift_right_preserving_sign/imm32/subx-name
22338     3/imm32/rm32-is-first-output
22339     0/imm32/no-r32
22340     0/imm32/no-imm32
22341     1/imm32/imm8-is-first-inout
22342     0/imm32/no-disp32
22343     0/imm32/no-xm32
22344     0/imm32/no-x32
22345     0x11/imm32/alloc-id:fake
22346     _Primitive-shift-mem-left-by-lit/imm32/next
22347 _Primitive-shift-mem-left-by-lit:  # (payload primitive)
22348     0x11/imm32/alloc-id:fake:payload
22349     # shift-left var1, lit => c1/shift 4/subop/left var1/rm32 lit/imm32
22350     0x11/imm32/alloc-id:fake
22351     _string-shift-left/imm32/name
22352     0x11/imm32/alloc-id:fake
22353     Int-var-and-literal/imm32/inouts
22354     0/imm32/no-outputs
22355     0/imm32/no-outputs
22356     0x11/imm32/alloc-id:fake
22357     _string_c1_subop_shift_left/imm32/subx-name
22358     1/imm32/rm32-is-first-inout
22359     0/imm32/no-r32
22360     0/imm32/no-imm32
22361     2/imm32/imm8-is-second-inout
22362     0/imm32/no-disp32
22363     0/imm32/no-xm32
22364     0/imm32/no-x32
22365     0x11/imm32/alloc-id:fake
22366     _Primitive-shift-mem-right-by-lit/imm32/next
22367 _Primitive-shift-mem-right-by-lit:  # (payload primitive)
22368     0x11/imm32/alloc-id:fake:payload
22369     # shift-right var1, lit => c1/shift 5/subop/right var1/rm32 lit/imm32
22370     0x11/imm32/alloc-id:fake
22371     _string-shift-right/imm32/name
22372     0x11/imm32/alloc-id:fake
22373     Int-var-and-literal/imm32/inouts
22374     0/imm32/no-outputs
22375     0/imm32/no-outputs
22376     0x11/imm32/alloc-id:fake
22377     _string_c1_subop_shift_right_padding_zeroes/imm32/subx-name
22378     1/imm32/rm32-is-first-inout
22379     0/imm32/no-r32
22380     0/imm32/no-imm32
22381     2/imm32/imm8-is-second-inout
22382     0/imm32/no-disp32
22383     0/imm32/no-xm32
22384     0/imm32/no-x32
22385     0x11/imm32/alloc-id:fake
22386     _Primitive-shift-mem-right-signed-by-lit/imm32/next
22387 _Primitive-shift-mem-right-signed-by-lit:  # (payload primitive)
22388     0x11/imm32/alloc-id:fake:payload
22389     # shift-right-signed var1, lit => c1/shift 7/subop/right-preserving-sign var1/rm32 lit/imm32
22390     0x11/imm32/alloc-id:fake
22391     _string-shift-right-signed/imm32/name
22392     0x11/imm32/alloc-id:fake
22393     Int-var-and-literal/imm32/inouts
22394     0/imm32/no-outputs
22395     0/imm32/no-outputs
22396     0x11/imm32/alloc-id:fake
22397     _string_c1_subop_shift_right_preserving_sign/imm32/subx-name
22398     1/imm32/rm32-is-first-inout
22399     0/imm32/no-r32
22400     0/imm32/no-imm32
22401     2/imm32/imm8-is-second-inout
22402     0/imm32/no-disp32
22403     0/imm32/no-xm32
22404     0/imm32/no-x32
22405     0x11/imm32/alloc-id:fake
22406     _Primitive-copy-to-eax/imm32/next
22407 # - copy
22408 _Primitive-copy-to-eax:  # (payload primitive)
22409     0x11/imm32/alloc-id:fake:payload
22410     # var/eax <- copy lit => b8/copy-to-eax lit/imm32
22411     0x11/imm32/alloc-id:fake
22412     _string-copy/imm32/name
22413     0x11/imm32/alloc-id:fake
22414     Single-lit-var/imm32/inouts
22415     0x11/imm32/alloc-id:fake
22416     Single-int-var-in-eax/imm32/outputs
22417     0x11/imm32/alloc-id:fake
22418     _string_b8_copy_to_eax/imm32/subx-name
22419     0/imm32/no-rm32
22420     0/imm32/no-r32
22421     1/imm32/imm32-is-first-inout
22422     0/imm32/no-imm8
22423     0/imm32/no-disp32
22424     0/imm32/no-xm32
22425     0/imm32/no-x32
22426     0x11/imm32/alloc-id:fake
22427     _Primitive-copy-to-ecx/imm32/next
22428 _Primitive-copy-to-ecx:  # (payload primitive)
22429     0x11/imm32/alloc-id:fake:payload
22430     # var/ecx <- copy lit => b9/copy-to-ecx lit/imm32
22431     0x11/imm32/alloc-id:fake
22432     _string-copy/imm32/name
22433     0x11/imm32/alloc-id:fake
22434     Single-lit-var/imm32/inouts
22435     0x11/imm32/alloc-id:fake
22436     Single-int-var-in-ecx/imm32/outputs
22437     0x11/imm32/alloc-id:fake
22438     _string_b9_copy_to_ecx/imm32/subx-name
22439     0/imm32/no-rm32
22440     0/imm32/no-r32
22441     1/imm32/imm32-is-first-inout
22442     0/imm32/no-imm8
22443     0/imm32/no-disp32
22444     0/imm32/no-xm32
22445     0/imm32/no-x32
22446     0x11/imm32/alloc-id:fake
22447     _Primitive-copy-to-edx/imm32/next
22448 _Primitive-copy-to-edx:  # (payload primitive)
22449     0x11/imm32/alloc-id:fake:payload
22450     # var/edx <- copy lit => ba/copy-to-edx lit/imm32
22451     0x11/imm32/alloc-id:fake
22452     _string-copy/imm32/name
22453     0x11/imm32/alloc-id:fake
22454     Single-lit-var/imm32/inouts
22455     0x11/imm32/alloc-id:fake
22456     Single-int-var-in-edx/imm32/outputs
22457     0x11/imm32/alloc-id:fake
22458     _string_ba_copy_to_edx/imm32/subx-name
22459     0/imm32/no-rm32
22460     0/imm32/no-r32
22461     1/imm32/imm32-is-first-inout
22462     0/imm32/no-imm8
22463     0/imm32/no-disp32
22464     0/imm32/no-xm32
22465     0/imm32/no-x32
22466     0x11/imm32/alloc-id:fake
22467     _Primitive-copy-to-ebx/imm32/next
22468 _Primitive-copy-to-ebx:  # (payload primitive)
22469     0x11/imm32/alloc-id:fake:payload
22470     # var/ebx <- copy lit => bb/copy-to-ebx lit/imm32
22471     0x11/imm32/alloc-id:fake
22472     _string-copy/imm32/name
22473     0x11/imm32/alloc-id:fake
22474     Single-lit-var/imm32/inouts
22475     0x11/imm32/alloc-id:fake
22476     Single-int-var-in-ebx/imm32/outputs
22477     0x11/imm32/alloc-id:fake
22478     _string_bb_copy_to_ebx/imm32/subx-name
22479     0/imm32/no-rm32
22480     0/imm32/no-r32
22481     1/imm32/imm32-is-first-inout
22482     0/imm32/no-imm8
22483     0/imm32/no-disp32
22484     0/imm32/no-xm32
22485     0/imm32/no-x32
22486     0x11/imm32/alloc-id:fake
22487     _Primitive-copy-to-esi/imm32/next
22488 _Primitive-copy-to-esi:  # (payload primitive)
22489     0x11/imm32/alloc-id:fake:payload
22490     # var/esi <- copy lit => be/copy-to-esi lit/imm32
22491     0x11/imm32/alloc-id:fake
22492     _string-copy/imm32/name
22493     0x11/imm32/alloc-id:fake
22494     Single-lit-var/imm32/inouts
22495     0x11/imm32/alloc-id:fake
22496     Single-int-var-in-esi/imm32/outputs
22497     0x11/imm32/alloc-id:fake
22498     _string_be_copy_to_esi/imm32/subx-name
22499     0/imm32/no-rm32
22500     0/imm32/no-r32
22501     1/imm32/imm32-is-first-inout
22502     0/imm32/no-imm8
22503     0/imm32/no-disp32
22504     0/imm32/no-xm32
22505     0/imm32/no-x32
22506     0x11/imm32/alloc-id:fake
22507     _Primitive-copy-to-edi/imm32/next
22508 _Primitive-copy-to-edi:  # (payload primitive)
22509     0x11/imm32/alloc-id:fake:payload
22510     # var/edi <- copy lit => bf/copy-to-edi lit/imm32
22511     0x11/imm32/alloc-id:fake
22512     _string-copy/imm32/name
22513     0x11/imm32/alloc-id:fake
22514     Single-lit-var/imm32/inouts
22515     0x11/imm32/alloc-id:fake
22516     Single-int-var-in-edi/imm32/outputs
22517     0x11/imm32/alloc-id:fake
22518     _string_bf_copy_to_edi/imm32/subx-name
22519     0/imm32/no-rm32
22520     0/imm32/no-r32
22521     1/imm32/imm32-is-first-inout
22522     0/imm32/no-imm8
22523     0/imm32/no-disp32
22524     0/imm32/no-xm32
22525     0/imm32/no-x32
22526     0x11/imm32/alloc-id:fake
22527     _Primitive-copy-reg-to-reg/imm32/next
22528 _Primitive-copy-reg-to-reg:  # (payload primitive)
22529     0x11/imm32/alloc-id:fake:payload
22530     # var1/reg <- copy var2/reg => 89/<- var1/rm32 var2/r32
22531     0x11/imm32/alloc-id:fake
22532     _string-copy/imm32/name
22533     0x11/imm32/alloc-id:fake
22534     Single-int-var-in-some-register/imm32/inouts
22535     0x11/imm32/alloc-id:fake
22536     Single-int-var-in-some-register/imm32/outputs
22537     0x11/imm32/alloc-id:fake
22538     _string_89_<-/imm32/subx-name
22539     3/imm32/rm32-is-first-output
22540     1/imm32/r32-is-first-inout
22541     0/imm32/no-imm32
22542     0/imm32/no-imm8
22543     0/imm32/no-disp32
22544     0/imm32/no-xm32
22545     0/imm32/no-x32
22546     0x11/imm32/alloc-id:fake
22547     _Primitive-copy-reg-to-mem/imm32/next
22548 _Primitive-copy-reg-to-mem:  # (payload primitive)
22549     0x11/imm32/alloc-id:fake:payload
22550     # copy-to var1 var2/reg => 89/<- var1 var2/r32
22551     0x11/imm32/alloc-id:fake
22552     _string-copy-to/imm32/name
22553     0x11/imm32/alloc-id:fake
22554     Two-args-int-stack-int-reg/imm32/inouts
22555     0/imm32/no-outputs
22556     0/imm32/no-outputs
22557     0x11/imm32/alloc-id:fake
22558     _string_89_<-/imm32/subx-name
22559     1/imm32/rm32-is-first-inout
22560     2/imm32/r32-is-second-inout
22561     0/imm32/no-imm32
22562     0/imm32/no-imm8
22563     0/imm32/no-disp32
22564     0/imm32/no-xm32
22565     0/imm32/no-x32
22566     0x11/imm32/alloc-id:fake
22567     _Primitive-copy-mem-to-reg/imm32/next
22568 _Primitive-copy-mem-to-reg:  # (payload primitive)
22569     0x11/imm32/alloc-id:fake:payload
22570     # var1/reg <- copy var2 => 8b/-> var2/rm32 var1/r32
22571     0x11/imm32/alloc-id:fake
22572     _string-copy/imm32/name
22573     0x11/imm32/alloc-id:fake
22574     Single-int-var-in-mem/imm32/inouts
22575     0x11/imm32/alloc-id:fake
22576     Single-int-var-in-some-register/imm32/outputs
22577     0x11/imm32/alloc-id:fake
22578     _string_8b_->/imm32/subx-name
22579     1/imm32/rm32-is-first-inout
22580     3/imm32/r32-is-first-output
22581     0/imm32/no-imm32
22582     0/imm32/no-imm8
22583     0/imm32/no-disp32
22584     0/imm32/no-xm32
22585     0/imm32/no-x32
22586     0x11/imm32/alloc-id:fake
22587     _Primitive-copy-lit-to-reg/imm32/next
22588 _Primitive-copy-lit-to-reg:  # (payload primitive)
22589     0x11/imm32/alloc-id:fake:payload
22590     # var1/reg <- copy lit => c7 0/subop/copy var1/rm32 lit/imm32
22591     0x11/imm32/alloc-id:fake
22592     _string-copy/imm32/name
22593     0x11/imm32/alloc-id:fake
22594     Single-lit-var/imm32/inouts
22595     0x11/imm32/alloc-id:fake
22596     Single-int-var-in-some-register/imm32/outputs
22597     0x11/imm32/alloc-id:fake
22598     _string_c7_subop_copy/imm32/subx-name
22599     3/imm32/rm32-is-first-output
22600     0/imm32/no-r32
22601     1/imm32/imm32-is-first-inout
22602     0/imm32/no-imm8
22603     0/imm32/no-disp32
22604     0/imm32/no-xm32
22605     0/imm32/no-x32
22606     0x11/imm32/alloc-id:fake
22607     _Primitive-copy-lit-to-mem/imm32/next
22608 _Primitive-copy-lit-to-mem:  # (payload primitive)
22609     0x11/imm32/alloc-id:fake:payload
22610     # copy-to var1, lit => c7 0/subop/copy var1/rm32 lit/imm32
22611     0x11/imm32/alloc-id:fake
22612     _string-copy-to/imm32/name
22613     0x11/imm32/alloc-id:fake
22614     Int-var-and-literal/imm32/inouts
22615     0/imm32/no-outputs
22616     0/imm32/no-outputs
22617     0x11/imm32/alloc-id:fake
22618     _string_c7_subop_copy/imm32/subx-name
22619     1/imm32/rm32-is-first-inout
22620     0/imm32/no-r32
22621     2/imm32/imm32-is-second-inout
22622     0/imm32/no-imm8
22623     0/imm32/no-disp32
22624     0/imm32/no-xm32
22625     0/imm32/no-x32
22626     0x11/imm32/alloc-id:fake
22627     _Primitive-copy-byte-from-reg/imm32/next
22628 # - copy byte
22629 _Primitive-copy-byte-from-reg:
22630     0x11/imm32/alloc-id:fake:payload
22631     # var/reg <- copy-byte var2/reg2 => 8a/byte-> %var2 var/r32
22632     0x11/imm32/alloc-id:fake
22633     _string-copy-byte/imm32/name
22634     0x11/imm32/alloc-id:fake
22635     Single-byte-var-in-some-register/imm32/inouts
22636     0x11/imm32/alloc-id:fake
22637     Single-byte-var-in-some-register/imm32/outputs
22638     0x11/imm32/alloc-id:fake
22639     _string_8a_copy_byte/imm32/subx-name
22640     1/imm32/rm32-is-first-inout
22641     3/imm32/r32-is-first-output
22642     0/imm32/no-imm32
22643     0/imm32/no-imm8
22644     0/imm32/no-disp32
22645     0/imm32/no-xm32
22646     0/imm32/no-x32
22647     0x11/imm32/alloc-id:fake
22648     _Primitive-copy-byte-from-mem/imm32/next
22649 _Primitive-copy-byte-from-mem:
22650     0x11/imm32/alloc-id:fake:payload
22651     # var/reg <- copy-byte *var2/reg2 => 8a/byte-> *var2 var/r32
22652     0x11/imm32/alloc-id:fake
22653     _string-copy-byte/imm32/name
22654     0x11/imm32/alloc-id:fake
22655     Single-byte-var-in-mem/imm32/inouts
22656     0x11/imm32/alloc-id:fake
22657     Single-byte-var-in-some-register/imm32/outputs
22658     0x11/imm32/alloc-id:fake
22659     _string_8a_copy_byte/imm32/subx-name
22660     1/imm32/rm32-is-first-inout
22661     3/imm32/r32-is-first-output
22662     0/imm32/no-imm32
22663     0/imm32/no-imm8
22664     0/imm32/no-disp32
22665     0/imm32/no-xm32
22666     0/imm32/no-x32
22667     0x11/imm32/alloc-id:fake
22668     _Primitive-copy-byte-to-mem/imm32/next
22669 _Primitive-copy-byte-to-mem:
22670     0x11/imm32/alloc-id:fake:payload
22671     # copy-byte-to *var1/reg1, var2/reg2 => 88/byte<- *reg1 reg2/r32
22672     0x11/imm32/alloc-id:fake
22673     _string-copy-byte-to/imm32/name
22674     0x11/imm32/alloc-id:fake
22675     Two-args-byte-stack-byte-reg/imm32/inouts
22676     0/imm32/no-outputs
22677     0/imm32/no-outputs
22678     0x11/imm32/alloc-id:fake
22679     _string_88_copy_byte/imm32/subx-name
22680     1/imm32/rm32-is-first-inout
22681     2/imm32/r32-is-second-inout
22682     0/imm32/no-imm32
22683     0/imm32/no-imm8
22684     0/imm32/no-disp32
22685     0/imm32/no-xm32
22686     0/imm32/no-x32
22687     0x11/imm32/alloc-id:fake
22688     _Primitive-address/imm32/next
22689 # - address
22690 _Primitive-address:  # (payload primitive)
22691     0x11/imm32/alloc-id:fake:payload
22692     # var1/reg <- address var2 => 8d/copy-address var2/rm32 var1/r32
22693     0x11/imm32/alloc-id:fake
22694     _string-address/imm32/name
22695     0x11/imm32/alloc-id:fake
22696     Single-int-var-in-mem/imm32/inouts
22697     0x11/imm32/alloc-id:fake
22698     Single-addr-var-in-some-register/imm32/outputs
22699     0x11/imm32/alloc-id:fake
22700     _string_8d_copy_address/imm32/subx-name
22701     1/imm32/rm32-is-first-inout
22702     3/imm32/r32-is-first-output
22703     0/imm32/no-imm32
22704     0/imm32/no-imm8
22705     0/imm32/no-disp32
22706     0/imm32/no-xm32
22707     0/imm32/no-x32
22708     0x11/imm32/alloc-id:fake
22709     _Primitive-compare-reg-with-reg/imm32/next
22710 # - compare
22711 _Primitive-compare-reg-with-reg:  # (payload primitive)
22712     0x11/imm32/alloc-id:fake:payload
22713     # compare var1/reg1 var2/reg2 => 39/compare var1/rm32 var2/r32
22714     0x11/imm32/alloc-id:fake
22715     _string-compare/imm32/name
22716     0x11/imm32/alloc-id:fake
22717     Two-int-args-in-regs/imm32/inouts
22718     0/imm32/no-outputs
22719     0/imm32/no-outputs
22720     0x11/imm32/alloc-id:fake
22721     _string_39_compare->/imm32/subx-name
22722     1/imm32/rm32-is-first-inout
22723     2/imm32/r32-is-second-inout
22724     0/imm32/no-imm32
22725     0/imm32/no-imm8
22726     0/imm32/no-disp32
22727     0/imm32/no-xm32
22728     0/imm32/no-x32
22729     0x11/imm32/alloc-id:fake
22730     _Primitive-compare-mem-with-reg/imm32/next
22731 _Primitive-compare-mem-with-reg:  # (payload primitive)
22732     0x11/imm32/alloc-id:fake:payload
22733     # compare var1 var2/reg => 39/compare var1/rm32 var2/r32
22734     0x11/imm32/alloc-id:fake
22735     _string-compare/imm32/name
22736     0x11/imm32/alloc-id:fake
22737     Two-args-int-stack-int-reg/imm32/inouts
22738     0/imm32/no-outputs
22739     0/imm32/no-outputs
22740     0x11/imm32/alloc-id:fake
22741     _string_39_compare->/imm32/subx-name
22742     1/imm32/rm32-is-first-inout
22743     2/imm32/r32-is-second-inout
22744     0/imm32/no-imm32
22745     0/imm32/no-imm8
22746     0/imm32/no-disp32
22747     0/imm32/no-xm32
22748     0/imm32/no-x32
22749     0x11/imm32/alloc-id:fake
22750     _Primitive-compare-reg-with-mem/imm32/next
22751 _Primitive-compare-reg-with-mem:  # (payload primitive)
22752     0x11/imm32/alloc-id:fake:payload
22753     # compare var1/reg var2 => 3b/compare<- var2/rm32 var1/r32
22754     0x11/imm32/alloc-id:fake
22755     _string-compare/imm32/name
22756     0x11/imm32/alloc-id:fake
22757     Two-args-int-reg-int-stack/imm32/inouts
22758     0/imm32/no-outputs
22759     0/imm32/no-outputs
22760     0x11/imm32/alloc-id:fake
22761     _string_3b_compare<-/imm32/subx-name
22762     2/imm32/rm32-is-second-inout
22763     1/imm32/r32-is-first-inout
22764     0/imm32/no-imm32
22765     0/imm32/no-imm8
22766     0/imm32/no-disp32
22767     0/imm32/no-xm32
22768     0/imm32/no-x32
22769     0x11/imm32/alloc-id:fake
22770     _Primitive-compare-eax-with-literal/imm32/next
22771 _Primitive-compare-eax-with-literal:  # (payload primitive)
22772     0x11/imm32/alloc-id:fake:payload
22773     # compare var1/eax n => 3d/compare-eax-with n/imm32
22774     0x11/imm32/alloc-id:fake
22775     _string-compare/imm32/name
22776     0x11/imm32/alloc-id:fake
22777     Two-args-int-eax-int-literal/imm32/inouts
22778     0/imm32/no-outputs
22779     0/imm32/no-outputs
22780     0x11/imm32/alloc-id:fake
22781     _string_3d_compare_eax_with/imm32/subx-name
22782     0/imm32/no-rm32
22783     0/imm32/no-r32
22784     2/imm32/imm32-is-second-inout
22785     0/imm32/no-imm8
22786     0/imm32/no-disp32
22787     0/imm32/no-xm32
22788     0/imm32/no-x32
22789     0x11/imm32/alloc-id:fake
22790     _Primitive-compare-reg-with-literal/imm32/next
22791 _Primitive-compare-reg-with-literal:  # (payload primitive)
22792     0x11/imm32/alloc-id:fake:payload
22793     # compare var1/reg n => 81 7/subop/compare %reg n/imm32
22794     0x11/imm32/alloc-id:fake
22795     _string-compare/imm32/name
22796     0x11/imm32/alloc-id:fake
22797     Int-var-in-register-and-literal/imm32/inouts
22798     0/imm32/no-outputs
22799     0/imm32/no-outputs
22800     0x11/imm32/alloc-id:fake
22801     _string_81_subop_compare/imm32/subx-name
22802     1/imm32/rm32-is-first-inout
22803     0/imm32/no-r32
22804     2/imm32/imm32-is-second-inout
22805     0/imm32/no-imm8
22806     0/imm32/no-disp32
22807     0/imm32/no-xm32
22808     0/imm32/no-x32
22809     0x11/imm32/alloc-id:fake
22810     _Primitive-compare-mem-with-literal/imm32/next
22811 _Primitive-compare-mem-with-literal:  # (payload primitive)
22812     0x11/imm32/alloc-id:fake:payload
22813     # compare var1 n => 81 7/subop/compare *(ebp+___) n/imm32
22814     0x11/imm32/alloc-id:fake
22815     _string-compare/imm32/name
22816     0x11/imm32/alloc-id:fake
22817     Int-var-and-literal/imm32/inouts
22818     0/imm32/no-outputs
22819     0/imm32/no-outputs
22820     0x11/imm32/alloc-id:fake
22821     _string_81_subop_compare/imm32/subx-name
22822     1/imm32/rm32-is-first-inout
22823     0/imm32/no-r32
22824     2/imm32/imm32-is-second-inout
22825     0/imm32/no-imm8
22826     0/imm32/no-disp32
22827     0/imm32/no-xm32
22828     0/imm32/no-x32
22829     0x11/imm32/alloc-id:fake
22830     _Primitive-negate-reg/imm32/next
22831 # - negate
22832 _Primitive-negate-reg:  # (payload primitive)
22833     0x11/imm32/alloc-id:fake:payload
22834     # var1/reg <- negate => f7 3/subop/negate var1/rm32
22835     0x11/imm32/alloc-id:fake
22836     _string-negate/imm32/name
22837     0/imm32/no-inouts
22838     0/imm32/no-inouts
22839     0x11/imm32/alloc-id:fake
22840     Single-int-var-in-some-register/imm32/outputs
22841     0x11/imm32/alloc-id:fake
22842     _string_f7_subop_negate/imm32/subx-name
22843     3/imm32/rm32-is-first-output
22844     0/imm32/no-r32
22845     0/imm32/no-imm32
22846     0/imm32/no-imm8
22847     0/imm32/no-disp32
22848     0/imm32/no-xm32
22849     0/imm32/no-x32
22850     0x11/imm32/alloc-id:fake
22851     _Primitive-negate-mem/imm32/next
22852 _Primitive-negate-mem:  # (payload primitive)
22853     0x11/imm32/alloc-id:fake:payload
22854     # negate var1 => f7 3/subop/negate var1/rm32
22855     0x11/imm32/alloc-id:fake
22856     _string-negate/imm32/name
22857     0x11/imm32/alloc-id:fake
22858     Single-int-var-in-mem/imm32/inouts
22859     0/imm32/no-outputs
22860     0/imm32/no-outputs
22861     0x11/imm32/alloc-id:fake
22862     _string_f7_subop_negate/imm32/subx-name
22863     1/imm32/rm32-is-first-inout
22864     0/imm32/no-r32
22865     0/imm32/no-imm32
22866     0/imm32/no-imm8
22867     0/imm32/no-disp32
22868     0/imm32/no-xm32
22869     0/imm32/no-x32
22870     0x11/imm32/alloc-id:fake
22871     _Primitive-multiply-reg-by-reg/imm32/next
22872 # - multiply
22873 _Primitive-multiply-reg-by-reg:  # (payload primitive)
22874     0x11/imm32/alloc-id:fake:payload
22875     # var1/reg <- multiply var2 => 0f af/multiply var2/rm32 var1/r32
22876     0x11/imm32/alloc-id:fake
22877     _string-multiply/imm32/name
22878     0x11/imm32/alloc-id:fake
22879     Single-int-var-in-some-register/imm32/inouts
22880     0x11/imm32/alloc-id:fake
22881     Single-int-var-in-some-register/imm32/outputs
22882     0x11/imm32/alloc-id:fake
22883     _string_0f_af_multiply/imm32/subx-name
22884     1/imm32/rm32-is-first-inout
22885     3/imm32/r32-is-first-output
22886     0/imm32/no-imm32
22887     0/imm32/no-imm8
22888     0/imm32/no-disp32
22889     0/imm32/no-xm32
22890     0/imm32/no-x32
22891     0x11/imm32/alloc-id:fake
22892     _Primitive-multiply-reg-by-mem/imm32/next
22893 _Primitive-multiply-reg-by-mem:  # (payload primitive)
22894     0x11/imm32/alloc-id:fake:payload
22895     # var1/reg <- multiply var2 => 0f af/multiply var2/rm32 var1/r32
22896     0x11/imm32/alloc-id:fake
22897     _string-multiply/imm32/name
22898     0x11/imm32/alloc-id:fake
22899     Single-int-var-in-mem/imm32/inouts
22900     0x11/imm32/alloc-id:fake
22901     Single-int-var-in-some-register/imm32/outputs
22902     0x11/imm32/alloc-id:fake
22903     _string_0f_af_multiply/imm32/subx-name
22904     1/imm32/rm32-is-first-inout
22905     3/imm32/r32-is-first-output
22906     0/imm32/no-imm32
22907     0/imm32/no-imm8
22908     0/imm32/no-disp32
22909     0/imm32/no-xm32
22910     0/imm32/no-x32
22911     0x11/imm32/alloc-id:fake
22912     _Primitive-convert-mem-to-xreg/imm32/next
22913 # - convert int to floating point
22914 _Primitive-convert-mem-to-xreg:  # (payload primitive)
22915     0x11/imm32/alloc-id:fake:payload
22916     # var1/xreg <- convert var2 => f3 0f 2a/convert-to-float var2/rm32 var1/x32
22917     0x11/imm32/alloc-id:fake
22918     _string-convert/imm32/name
22919     0x11/imm32/alloc-id:fake
22920     Single-int-var-in-mem/imm32/inouts
22921     0x11/imm32/alloc-id:fake
22922     Single-float-var-in-some-register/imm32/outputs
22923     0x11/imm32/alloc-id:fake
22924     _string_f3_0f_2a_convert_to_float/imm32/subx-name
22925     1/imm32/rm32-is-first-inout
22926     0/imm32/no-r32
22927     0/imm32/no-imm32
22928     0/imm32/no-imm8
22929     0/imm32/no-disp32
22930     0/imm32/no-xm32
22931     3/imm32/x32-is-first-output
22932     0x11/imm32/alloc-id:fake
22933     _Primitive-convert-reg-to-xreg/imm32/next
22934 _Primitive-convert-reg-to-xreg:  # (payload primitive)
22935     0x11/imm32/alloc-id:fake:payload
22936     # var1/xreg <- convert var2/reg => f3 0f 2a/convert-to-float var2/rm32 var1/x32
22937     0x11/imm32/alloc-id:fake
22938     _string-convert/imm32/name
22939     0x11/imm32/alloc-id:fake
22940     Single-int-var-in-some-register/imm32/inouts
22941     0x11/imm32/alloc-id:fake
22942     Single-float-var-in-some-register/imm32/outputs
22943     0x11/imm32/alloc-id:fake
22944     _string_f3_0f_2a_convert_to_float/imm32/subx-name
22945     1/imm32/rm32-is-first-inout
22946     0/imm32/no-r32
22947     0/imm32/no-imm32
22948     0/imm32/no-imm8
22949     0/imm32/no-disp32
22950     0/imm32/no-xm32
22951     3/imm32/x32-is-first-output
22952     0x11/imm32/alloc-id:fake
22953     _Primitive-convert-xmem-to-reg/imm32/next
22954 # - convert floating point to int
22955 _Primitive-convert-xmem-to-reg:  # (payload primitive)
22956     0x11/imm32/alloc-id:fake:payload
22957     # var1/reg <- convert var2 => f3 0f 2d/convert-to-int var2/xm32 var1/r32
22958     0x11/imm32/alloc-id:fake
22959     _string-convert/imm32/name
22960     0x11/imm32/alloc-id:fake
22961     Single-float-var-in-mem/imm32/inouts
22962     0x11/imm32/alloc-id:fake
22963     Single-int-var-in-some-register/imm32/outputs
22964     0x11/imm32/alloc-id:fake
22965     _string_f3_0f_2d_convert_to_int/imm32/subx-name
22966     0/imm32/no-rm32
22967     3/imm32/r32-is-first-output
22968     0/imm32/no-imm32
22969     0/imm32/no-imm8
22970     0/imm32/no-disp32
22971     1/imm32/xm32-is-first-inout
22972     0/imm32/no-x32
22973     0x11/imm32/alloc-id:fake
22974     _Primitive-convert-xreg-to-reg/imm32/next
22975 _Primitive-convert-xreg-to-reg:  # (payload primitive)
22976     0x11/imm32/alloc-id:fake:payload
22977     # var1/reg <- convert var2/xreg => f3 0f 2d/convert-to-int var2/xm32 var1/r32
22978     0x11/imm32/alloc-id:fake
22979     _string-convert/imm32/name
22980     0x11/imm32/alloc-id:fake
22981     Single-float-var-in-some-register/imm32/inouts
22982     0x11/imm32/alloc-id:fake
22983     Single-int-var-in-some-register/imm32/outputs
22984     0x11/imm32/alloc-id:fake
22985     _string_f3_0f_2d_convert_to_int/imm32/subx-name
22986     0/imm32/no-rm32
22987     3/imm32/r32-is-first-output
22988     0/imm32/no-imm32
22989     0/imm32/no-imm8
22990     0/imm32/no-disp32
22991     1/imm32/xm32-is-first-inout
22992     0/imm32/no-x32
22993     0x11/imm32/alloc-id:fake
22994     _Primitive-truncate-xmem-to-reg/imm32/next
22995 _Primitive-truncate-xmem-to-reg:  # (payload primitive)
22996     0x11/imm32/alloc-id:fake:payload
22997     # var1/reg <- truncate var2 => f3 0f 2c/truncate-to-int var2/xm32 var1/r32
22998     0x11/imm32/alloc-id:fake
22999     _string-truncate/imm32/name
23000     0x11/imm32/alloc-id:fake
23001     Single-float-var-in-mem/imm32/inouts
23002     0x11/imm32/alloc-id:fake
23003     Single-int-var-in-some-register/imm32/outputs
23004     0x11/imm32/alloc-id:fake
23005     _string_f3_0f_2c_truncate_to_int/imm32/subx-name
23006     0/imm32/no-rm32
23007     3/imm32/r32-is-first-output
23008     0/imm32/no-imm32
23009     0/imm32/no-imm8
23010     0/imm32/no-disp32
23011     1/imm32/xm32-is-first-inout
23012     0/imm32/no-x32
23013     0x11/imm32/alloc-id:fake
23014     _Primitive-truncate-xreg-to-reg/imm32/next
23015 _Primitive-truncate-xreg-to-reg:  # (payload primitive)
23016     0x11/imm32/alloc-id:fake:payload
23017     # var1/reg <- truncate var2/xreg => f3 0f 2c/truncate-to-int var2/xm32 var1/r32
23018     0x11/imm32/alloc-id:fake
23019     _string-truncate/imm32/name
23020     0x11/imm32/alloc-id:fake
23021     Single-float-var-in-some-register/imm32/inouts
23022     0x11/imm32/alloc-id:fake
23023     Single-int-var-in-some-register/imm32/outputs
23024     0x11/imm32/alloc-id:fake
23025     _string_f3_0f_2c_truncate_to_int/imm32/subx-name
23026     0/imm32/no-rm32
23027     3/imm32/r32-is-first-output
23028     0/imm32/no-imm32
23029     0/imm32/no-imm8
23030     0/imm32/no-disp32
23031     1/imm32/xm32-is-first-inout
23032     0/imm32/no-x32
23033     0x11/imm32/alloc-id:fake
23034     _Primitive-reinterpret-xmem-as-reg/imm32/next
23035 # - reinterpret bytes (just for debugging)
23036 _Primitive-reinterpret-xmem-as-reg:  # (payload primitive)
23037     0x11/imm32/alloc-id:fake:payload
23038     # var1/reg <- reinterpret var2 => 8b/-> var2/xm32 var1/r32
23039     0x11/imm32/alloc-id:fake
23040     _string-reinterpret/imm32/name
23041     0x11/imm32/alloc-id:fake
23042     Single-float-var-in-mem/imm32/inouts
23043     0x11/imm32/alloc-id:fake
23044     Single-int-var-in-some-register/imm32/outputs
23045     0x11/imm32/alloc-id:fake
23046     _string_8b_->/imm32/subx-name
23047     0/imm32/no-rm32
23048     3/imm32/r32-is-first-output
23049     0/imm32/no-imm32
23050     0/imm32/no-imm8
23051     0/imm32/no-disp32
23052     1/imm32/xm32-is-first-inout
23053     0/imm32/no-x32
23054     0x11/imm32/alloc-id:fake
23055     _Primitive-reinterpret-mem-as-xreg/imm32/next
23056 _Primitive-reinterpret-mem-as-xreg:  # (payload primitive)
23057     0x11/imm32/alloc-id:fake:payload
23058     # var1/xreg <- reinterpret var2 => f3 0f 10/-> var2/rm32 var1/x32
23059     0x11/imm32/alloc-id:fake
23060     _string-reinterpret/imm32/name
23061     0x11/imm32/alloc-id:fake
23062     Single-int-var-in-mem/imm32/inouts
23063     0x11/imm32/alloc-id:fake
23064     Single-float-var-in-some-register/imm32/outputs
23065     0x11/imm32/alloc-id:fake
23066     _string_f3_0f_10_copy/imm32/subx-name
23067     1/imm32/rm32-is-first-inout
23068     0/imm32/no-r32
23069     0/imm32/no-imm32
23070     0/imm32/no-imm8
23071     0/imm32/no-disp32
23072     0/imm32/no-xm32
23073     3/imm32/x32-is-first-output
23074     0x11/imm32/alloc-id:fake
23075     _Primitive-copy-xreg-to-xreg/imm32/next
23076 # - floating-point copy
23077 _Primitive-copy-xreg-to-xreg:  # (payload primitive)
23078     0x11/imm32/alloc-id:fake:payload
23079     # var1/xreg <- copy var2/xreg => f3 0f 11/<- var1/xm32 var2/x32
23080     0x11/imm32/alloc-id:fake
23081     _string-copy/imm32/name
23082     0x11/imm32/alloc-id:fake
23083     Single-float-var-in-some-register/imm32/inouts
23084     0x11/imm32/alloc-id:fake
23085     Single-float-var-in-some-register/imm32/outputs
23086     0x11/imm32/alloc-id:fake
23087     _string_f3_0f_11_copy/imm32/subx-name
23088     0/imm32/no-rm32
23089     0/imm32/no-r32
23090     0/imm32/no-imm32
23091     0/imm32/no-imm8
23092     0/imm32/no-disp32
23093     3/imm32/xm32-is-first-output
23094     1/imm32/x32-is-first-inout
23095     0x11/imm32/alloc-id:fake
23096     _Primitive-copy-xreg-to-mem/imm32/next
23097 _Primitive-copy-xreg-to-mem:  # (payload primitive)
23098     0x11/imm32/alloc-id:fake:payload
23099     # copy-to var1 var2/xreg => f3 0f 11/<- var1 var2/x32
23100     0x11/imm32/alloc-id:fake
23101     _string-copy-to/imm32/name
23102     0x11/imm32/alloc-id:fake
23103     Two-args-float-stack-float-reg/imm32/inouts
23104     0/imm32/no-outputs
23105     0/imm32/no-outputs
23106     0x11/imm32/alloc-id:fake
23107     _string_f3_0f_11_copy/imm32/subx-name
23108     0/imm32/no-rm32
23109     0/imm32/no-r32
23110     0/imm32/no-imm32
23111     0/imm32/no-imm8
23112     0/imm32/no-disp32
23113     1/imm32/xm32-is-first-inout
23114     2/imm32/x32-is-second-inout
23115     0x11/imm32/alloc-id:fake
23116     _Primitive-copy-mem-to-xreg/imm32/next
23117 _Primitive-copy-mem-to-xreg:  # (payload primitive)
23118     0x11/imm32/alloc-id:fake:payload
23119     # var1/xreg <- copy var2 => f3 0f 10/-> var2/rm32 var1/x32
23120     0x11/imm32/alloc-id:fake
23121     _string-copy/imm32/name
23122     0x11/imm32/alloc-id:fake
23123     Single-float-var-in-mem/imm32/inouts
23124     0x11/imm32/alloc-id:fake
23125     Single-float-var-in-some-register/imm32/outputs
23126     0x11/imm32/alloc-id:fake
23127     _string_f3_0f_10_copy/imm32/subx-name
23128     0/imm32/no-rm32
23129     0/imm32/no-r32
23130     0/imm32/no-imm32
23131     0/imm32/no-imm8
23132     0/imm32/no-disp32
23133     1/imm32/xm32-is-first-inout
23134     3/imm32/x32-is-first-output
23135     0x11/imm32/alloc-id:fake
23136     _Primitive-address-of-xmem/imm32/next
23137 # - floating-point-address
23138 _Primitive-address-of-xmem:  # (payload primitive)
23139     0x11/imm32/alloc-id:fake:payload
23140     # var1/reg <- address var2 => 8d/copy-address var2/rm32 var1/r32
23141     0x11/imm32/alloc-id:fake
23142     _string-address/imm32/name
23143     0x11/imm32/alloc-id:fake
23144     Single-float-var-in-mem/imm32/inouts
23145     0x11/imm32/alloc-id:fake
23146     Single-addr-var-in-some-register/imm32/outputs
23147     0x11/imm32/alloc-id:fake
23148     _string_8d_copy_address/imm32/subx-name
23149     1/imm32/rm32-is-first-inout
23150     3/imm32/r32-is-first-output
23151     0/imm32/no-imm32
23152     0/imm32/no-imm8
23153     0/imm32/no-disp32
23154     0/imm32/no-xm32
23155     0/imm32/no-x32
23156     0x11/imm32/alloc-id:fake
23157     _Primitive-add-xreg-to-xreg/imm32/next
23158 # - floating-point add
23159 _Primitive-add-xreg-to-xreg:  # (payload primitive)
23160     0x11/imm32/alloc-id:fake:payload
23161     # var1/xreg <- add var2/xreg => f3 0f 58/add var1/xm32 var2/x32
23162     0x11/imm32/alloc-id:fake
23163     _string-add/imm32/name
23164     0x11/imm32/alloc-id:fake
23165     Single-float-var-in-some-register/imm32/inouts
23166     0x11/imm32/alloc-id:fake
23167     Single-float-var-in-some-register/imm32/outputs
23168     0x11/imm32/alloc-id:fake
23169     _string_f3_0f_58_add/imm32/subx-name
23170     0/imm32/no-rm32
23171     0/imm32/no-r32
23172     0/imm32/no-imm32
23173     0/imm32/no-imm8
23174     0/imm32/no-disp32
23175     1/imm32/xm32-is-first-inout
23176     3/imm32/x32-is-first-output
23177     0x11/imm32/alloc-id:fake
23178     _Primitive-add-mem-to-xreg/imm32/next
23179 _Primitive-add-mem-to-xreg:  # (payload primitive)
23180     0x11/imm32/alloc-id:fake:payload
23181     # var1/xreg <- add var2 => f3 0f 58/add var2/xm32 var1/x32
23182     0x11/imm32/alloc-id:fake
23183     _string-add/imm32/name
23184     0x11/imm32/alloc-id:fake
23185     Single-float-var-in-mem/imm32/inouts
23186     0x11/imm32/alloc-id:fake
23187     Single-float-var-in-some-register/imm32/outputs
23188     0x11/imm32/alloc-id:fake
23189     _string_f3_0f_58_add/imm32/subx-name
23190     0/imm32/no-rm32
23191     0/imm32/no-r32
23192     0/imm32/no-imm32
23193     0/imm32/no-imm8
23194     0/imm32/no-disp32
23195     1/imm32/xm32-is-first-inout
23196     3/imm32/x32-is-first-output
23197     0x11/imm32/alloc-id:fake
23198     _Primitive-subtract-xreg-from-xreg/imm32/next
23199 # - floating-point subtract
23200 _Primitive-subtract-xreg-from-xreg:  # (payload primitive)
23201     0x11/imm32/alloc-id:fake:payload
23202     # var1/xreg <- subtract var2/xreg => f3 0f 5c/subtract var1/xm32 var2/x32
23203     0x11/imm32/alloc-id:fake
23204     _string-subtract/imm32/name
23205     0x11/imm32/alloc-id:fake
23206     Single-float-var-in-some-register/imm32/inouts
23207     0x11/imm32/alloc-id:fake
23208     Single-float-var-in-some-register/imm32/outputs
23209     0x11/imm32/alloc-id:fake
23210     _string_f3_0f_5c_subtract/imm32/subx-name
23211     0/imm32/no-rm32
23212     0/imm32/no-r32
23213     0/imm32/no-imm32
23214     0/imm32/no-imm8
23215     0/imm32/no-disp32
23216     1/imm32/xm32-is-first-inout
23217     3/imm32/x32-is-first-output
23218     0x11/imm32/alloc-id:fake
23219     _Primitive-subtract-mem-from-xreg/imm32/next
23220 _Primitive-subtract-mem-from-xreg:  # (payload primitive)
23221     0x11/imm32/alloc-id:fake:payload
23222     # var1/xreg <- subtract var2 => f3 0f 5c/subtract var2/xm32 var1/x32
23223     0x11/imm32/alloc-id:fake
23224     _string-subtract/imm32/name
23225     0x11/imm32/alloc-id:fake
23226     Single-float-var-in-mem/imm32/inouts
23227     0x11/imm32/alloc-id:fake
23228     Single-float-var-in-some-register/imm32/outputs
23229     0x11/imm32/alloc-id:fake
23230     _string_f3_0f_5c_subtract/imm32/subx-name
23231     0/imm32/no-rm32
23232     0/imm32/no-r32
23233     0/imm32/no-imm32
23234     0/imm32/no-imm8
23235     0/imm32/no-disp32
23236     1/imm32/xm32-is-first-inout
23237     3/imm32/x32-is-first-output
23238     0x11/imm32/alloc-id:fake
23239     _Primitive-multiply-xreg-by-xreg/imm32/next
23240 # - floating-point multiply
23241 _Primitive-multiply-xreg-by-xreg:  # (payload primitive)
23242     0x11/imm32/alloc-id:fake:payload
23243     # var1/xreg <- multiply var2 => f3 0f 59/multiply var2/xm32 var1/x32
23244     0x11/imm32/alloc-id:fake
23245     _string-multiply/imm32/name
23246     0x11/imm32/alloc-id:fake
23247     Single-float-var-in-some-register/imm32/inouts
23248     0x11/imm32/alloc-id:fake
23249     Single-float-var-in-some-register/imm32/outputs
23250     0x11/imm32/alloc-id:fake
23251     _string_f3_0f_59_multiply/imm32/subx-name
23252     0/imm32/no-rm32
23253     0/imm32/no-r32
23254     0/imm32/no-imm32
23255     0/imm32/no-imm8
23256     0/imm32/no-disp32
23257     1/imm32/xm32-is-first-inout
23258     3/imm32/x32-is-first-output
23259     0x11/imm32/alloc-id:fake
23260     _Primitive-multiply-xreg-by-mem/imm32/next
23261 _Primitive-multiply-xreg-by-mem:  # (payload primitive)
23262     0x11/imm32/alloc-id:fake:payload
23263     # var1/xreg <- multiply var2 => 53 0f 59/multiply var2/xm32 var1/x32
23264     0x11/imm32/alloc-id:fake
23265     _string-multiply/imm32/name
23266     0x11/imm32/alloc-id:fake
23267     Single-float-var-in-mem/imm32/inouts
23268     0x11/imm32/alloc-id:fake
23269     Single-float-var-in-some-register/imm32/outputs
23270     0x11/imm32/alloc-id:fake
23271     _string_f3_0f_59_multiply/imm32/subx-name
23272     0/imm32/no-rm32
23273     0/imm32/no-r32
23274     0/imm32/no-imm32
23275     0/imm32/no-imm8
23276     0/imm32/no-disp32
23277     1/imm32/xm32-is-first-inout
23278     3/imm32/x32-is-first-output
23279     0x11/imm32/alloc-id:fake
23280     _Primitive-divide-xreg-by-xreg/imm32/next
23281 # - floating-point divide
23282 _Primitive-divide-xreg-by-xreg:  # (payload primitive)
23283     0x11/imm32/alloc-id:fake:payload
23284     # var1/xreg <- divide var2 => f3 0f 5e/divide var2/xm32 var1/x32
23285     0x11/imm32/alloc-id:fake
23286     _string-divide/imm32/name
23287     0x11/imm32/alloc-id:fake
23288     Single-float-var-in-some-register/imm32/inouts
23289     0x11/imm32/alloc-id:fake
23290     Single-float-var-in-some-register/imm32/outputs
23291     0x11/imm32/alloc-id:fake
23292     _string_f3_0f_5e_divide/imm32/subx-name
23293     0/imm32/no-rm32
23294     0/imm32/no-r32
23295     0/imm32/no-imm32
23296     0/imm32/no-imm8
23297     0/imm32/no-disp32
23298     1/imm32/xm32-is-first-inout
23299     3/imm32/x32-is-first-output
23300     0x11/imm32/alloc-id:fake
23301     _Primitive-divide-xreg-by-mem/imm32/next
23302 _Primitive-divide-xreg-by-mem:  # (payload primitive)
23303     0x11/imm32/alloc-id:fake:payload
23304     # var1/xreg <- divide var2 => f3 0f 5e/divide var2/xm32 var1/x32
23305     0x11/imm32/alloc-id:fake
23306     _string-divide/imm32/name
23307     0x11/imm32/alloc-id:fake
23308     Single-float-var-in-mem/imm32/inouts
23309     0x11/imm32/alloc-id:fake
23310     Single-float-var-in-some-register/imm32/outputs
23311     0x11/imm32/alloc-id:fake
23312     _string_f3_0f_5e_divide/imm32/subx-name
23313     0/imm32/no-rm32
23314     0/imm32/no-r32
23315     0/imm32/no-imm32
23316     0/imm32/no-imm8
23317     0/imm32/no-disp32
23318     1/imm32/xm32-is-first-inout
23319     3/imm32/x32-is-first-output
23320     0x11/imm32/alloc-id:fake
23321     _Primitive-max-xreg-with-xreg/imm32/next
23322 # - floating-point maximum
23323 _Primitive-max-xreg-with-xreg:  # (payload primitive)
23324     0x11/imm32/alloc-id:fake:payload
23325     # var1/xreg <- max var2 => f3 0f 5f/max var2/xm32 var1/x32
23326     0x11/imm32/alloc-id:fake
23327     _string-max/imm32/name
23328     0x11/imm32/alloc-id:fake
23329     Single-float-var-in-some-register/imm32/inouts
23330     0x11/imm32/alloc-id:fake
23331     Single-float-var-in-some-register/imm32/outputs
23332     0x11/imm32/alloc-id:fake
23333     _string_f3_0f_5f_max/imm32/subx-name
23334     0/imm32/no-rm32
23335     0/imm32/no-r32
23336     0/imm32/no-imm32
23337     0/imm32/no-imm8
23338     0/imm32/no-disp32
23339     1/imm32/xm32-is-first-inout
23340     3/imm32/x32-is-first-output
23341     0x11/imm32/alloc-id:fake
23342     _Primitive-max-xreg-with-mem/imm32/next
23343 _Primitive-max-xreg-with-mem:  # (payload primitive)
23344     0x11/imm32/alloc-id:fake:payload
23345     # var1/xreg <- divide var2 => f3 0f 5f/max var2/xm32 var1/x32
23346     0x11/imm32/alloc-id:fake
23347     _string-max/imm32/name
23348     0x11/imm32/alloc-id:fake
23349     Single-float-var-in-mem/imm32/inouts
23350     0x11/imm32/alloc-id:fake
23351     Single-float-var-in-some-register/imm32/outputs
23352     0x11/imm32/alloc-id:fake
23353     _string_f3_0f_5f_max/imm32/subx-name
23354     0/imm32/no-rm32
23355     0/imm32/no-r32
23356     0/imm32/no-imm32
23357     0/imm32/no-imm8
23358     0/imm32/no-disp32
23359     1/imm32/xm32-is-first-inout
23360     3/imm32/x32-is-first-output
23361     0x11/imm32/alloc-id:fake
23362     _Primitive-min-xreg-with-xreg/imm32/next
23363 # - floating-point minimum
23364 _Primitive-min-xreg-with-xreg:  # (payload primitive)
23365     0x11/imm32/alloc-id:fake:payload
23366     # var1/xreg <- divide var2 => f3 0f 5d/min var2/xm32 var1/x32
23367     0x11/imm32/alloc-id:fake
23368     _string-min/imm32/name
23369     0x11/imm32/alloc-id:fake
23370     Single-float-var-in-some-register/imm32/inouts
23371     0x11/imm32/alloc-id:fake
23372     Single-float-var-in-some-register/imm32/outputs
23373     0x11/imm32/alloc-id:fake
23374     _string_f3_0f_5d_min/imm32/subx-name
23375     0/imm32/no-rm32
23376     0/imm32/no-r32
23377     0/imm32/no-imm32
23378     0/imm32/no-imm8
23379     0/imm32/no-disp32
23380     1/imm32/xm32-is-first-inout
23381     3/imm32/x32-is-first-output
23382     0x11/imm32/alloc-id:fake
23383     _Primitive-min-xreg-with-mem/imm32/next
23384 _Primitive-min-xreg-with-mem:  # (payload primitive)
23385     0x11/imm32/alloc-id:fake:payload
23386     # var1/xreg <- divide var2 => f3 0f 5d/min var2/xm32 var1/x32
23387     0x11/imm32/alloc-id:fake
23388     _string-min/imm32/name
23389     0x11/imm32/alloc-id:fake
23390     Single-float-var-in-mem/imm32/inouts
23391     0x11/imm32/alloc-id:fake
23392     Single-float-var-in-some-register/imm32/outputs
23393     0x11/imm32/alloc-id:fake
23394     _string_f3_0f_5d_min/imm32/subx-name
23395     0/imm32/no-rm32
23396     0/imm32/no-r32
23397     0/imm32/no-imm32
23398     0/imm32/no-imm8
23399     0/imm32/no-disp32
23400     1/imm32/xm32-is-first-inout
23401     3/imm32/x32-is-first-output
23402     0x11/imm32/alloc-id:fake
23403     _Primitive-reciprocal-xreg-to-xreg/imm32/next
23404 # - floating-point reciprocal
23405 _Primitive-reciprocal-xreg-to-xreg:  # (payload primitive)
23406     0x11/imm32/alloc-id:fake:payload
23407     # var1/xreg <- reciprocal var2 => f3 0f 53/reciprocal var2/xm32 var1/x32
23408     0x11/imm32/alloc-id:fake
23409     _string-reciprocal/imm32/name
23410     0x11/imm32/alloc-id:fake
23411     Single-float-var-in-some-register/imm32/inouts
23412     0x11/imm32/alloc-id:fake
23413     Single-float-var-in-some-register/imm32/outputs
23414     0x11/imm32/alloc-id:fake
23415     _string_f3_0f_53_reciprocal/imm32/subx-name
23416     0/imm32/no-rm32
23417     0/imm32/no-r32
23418     0/imm32/no-imm32
23419     0/imm32/no-imm8
23420     0/imm32/no-disp32
23421     1/imm32/xm32-is-first-inout
23422     3/imm32/x32-is-first-output
23423     0x11/imm32/alloc-id:fake
23424     _Primitive-reciprocal-mem-to-xreg/imm32/next
23425 _Primitive-reciprocal-mem-to-xreg:  # (payload primitive)
23426     0x11/imm32/alloc-id:fake:payload
23427     # var1/xreg <- divide var2 => f3 0f 53/reciprocal var2/xm32 var1/x32
23428     0x11/imm32/alloc-id:fake
23429     _string-reciprocal/imm32/name
23430     0x11/imm32/alloc-id:fake
23431     Single-float-var-in-mem/imm32/inouts
23432     0x11/imm32/alloc-id:fake
23433     Single-float-var-in-some-register/imm32/outputs
23434     0x11/imm32/alloc-id:fake
23435     _string_f3_0f_53_reciprocal/imm32/subx-name
23436     0/imm32/no-rm32
23437     0/imm32/no-r32
23438     0/imm32/no-imm32
23439     0/imm32/no-imm8
23440     0/imm32/no-disp32
23441     1/imm32/xm32-is-first-inout
23442     3/imm32/x32-is-first-output
23443     0x11/imm32/alloc-id:fake
23444     _Primitive-square-root-xreg-to-xreg/imm32/next
23445 # - floating-point square root
23446 _Primitive-square-root-xreg-to-xreg:  # (payload primitive)
23447     0x11/imm32/alloc-id:fake:payload
23448     # var1/xreg <- square-root var2 => f3 0f 51/square-root var2/xm32 var1/x32
23449     0x11/imm32/alloc-id:fake
23450     _string-square-root/imm32/name
23451     0x11/imm32/alloc-id:fake
23452     Single-float-var-in-some-register/imm32/inouts
23453     0x11/imm32/alloc-id:fake
23454     Single-float-var-in-some-register/imm32/outputs
23455     0x11/imm32/alloc-id:fake
23456     _string_f3_0f_51_square_root/imm32/subx-name
23457     0/imm32/no-rm32
23458     0/imm32/no-r32
23459     0/imm32/no-imm32
23460     0/imm32/no-imm8
23461     0/imm32/no-disp32
23462     1/imm32/xm32-is-first-inout
23463     3/imm32/x32-is-first-output
23464     0x11/imm32/alloc-id:fake
23465     _Primitive-square-root-mem-to-xreg/imm32/next
23466 _Primitive-square-root-mem-to-xreg:  # (payload primitive)
23467     0x11/imm32/alloc-id:fake:payload
23468     # var1/xreg <- divide var2 => f3 0f 51/square-root var2/xm32 var1/x32
23469     0x11/imm32/alloc-id:fake
23470     _string-square-root/imm32/name
23471     0x11/imm32/alloc-id:fake
23472     Single-float-var-in-mem/imm32/inouts
23473     0x11/imm32/alloc-id:fake
23474     Single-float-var-in-some-register/imm32/outputs
23475     0x11/imm32/alloc-id:fake
23476     _string_f3_0f_51_square_root/imm32/subx-name
23477     0/imm32/no-rm32
23478     0/imm32/no-r32
23479     0/imm32/no-imm32
23480     0/imm32/no-imm8
23481     0/imm32/no-disp32
23482     1/imm32/xm32-is-first-inout
23483     3/imm32/x32-is-first-output
23484     0x11/imm32/alloc-id:fake
23485     _Primitive-inverse-square-root-xreg-to-xreg/imm32/next
23486 # - floating-point inverse square root 1/sqrt(x)
23487 _Primitive-inverse-square-root-xreg-to-xreg:  # (payload primitive)
23488     0x11/imm32/alloc-id:fake:payload
23489     # var1/xreg <- reciprocal var2 => f3 0f 52/inverse-square-root var2/xm32 var1/x32
23490     0x11/imm32/alloc-id:fake
23491     _string-inverse-square-root/imm32/name
23492     0x11/imm32/alloc-id:fake
23493     Single-float-var-in-some-register/imm32/inouts
23494     0x11/imm32/alloc-id:fake
23495     Single-float-var-in-some-register/imm32/outputs
23496     0x11/imm32/alloc-id:fake
23497     _string_f3_0f_52_inverse_square_root/imm32/subx-name
23498     0/imm32/no-rm32
23499     0/imm32/no-r32
23500     0/imm32/no-imm32
23501     0/imm32/no-imm8
23502     0/imm32/no-disp32
23503     1/imm32/xm32-is-first-inout
23504     3/imm32/x32-is-first-output
23505     0x11/imm32/alloc-id:fake
23506     _Primitive-inverse-square-root-mem-to-xreg/imm32/next
23507 _Primitive-inverse-square-root-mem-to-xreg:  # (payload primitive)
23508     0x11/imm32/alloc-id:fake:payload
23509     # var1/xreg <- divide var2 => f3 0f 52/inverse-square-root var2/xm32 var1/x32
23510     0x11/imm32/alloc-id:fake
23511     _string-inverse-square-root/imm32/name
23512     0x11/imm32/alloc-id:fake
23513     Single-float-var-in-mem/imm32/inouts
23514     0x11/imm32/alloc-id:fake
23515     Single-float-var-in-some-register/imm32/outputs
23516     0x11/imm32/alloc-id:fake
23517     _string_f3_0f_52_inverse_square_root/imm32/subx-name
23518     0/imm32/no-rm32
23519     0/imm32/no-r32
23520     0/imm32/no-imm32
23521     0/imm32/no-imm8
23522     0/imm32/no-disp32
23523     1/imm32/xm32-is-first-inout
23524     3/imm32/x32-is-first-output
23525     0x11/imm32/alloc-id:fake
23526     _Primitive-compare-xreg-with-xreg/imm32/next
23527 # - floating-point compare
23528 _Primitive-compare-xreg-with-xreg:  # (payload primitive)
23529     0x11/imm32/alloc-id:fake:payload
23530     # compare var1/reg1 var2/reg2 => 0f 2f/compare var2/x32 var1/xm32
23531     0x11/imm32/alloc-id:fake
23532     _string-compare/imm32/name
23533     0x11/imm32/alloc-id:fake
23534     Two-float-args-in-regs/imm32/inouts
23535     0/imm32/no-outputs
23536     0/imm32/no-outputs
23537     0x11/imm32/alloc-id:fake
23538     _string_0f_2f_compare/imm32/subx-name
23539     0/imm32/no-rm32
23540     0/imm32/no-r32
23541     0/imm32/no-imm32
23542     0/imm32/no-imm8
23543     0/imm32/no-disp32
23544     1/imm32/xm32-is-first-inout
23545     2/imm32/x32-is-second-inout
23546     0x11/imm32/alloc-id:fake
23547     _Primitive-compare-xreg-with-mem/imm32/next
23548 _Primitive-compare-xreg-with-mem:  # (payload primitive)
23549     0x11/imm32/alloc-id:fake:payload
23550     # compare var1/xreg var2 => 0f 2f/compare var1/x32 var2/xm32
23551     0x11/imm32/alloc-id:fake
23552     _string-compare/imm32/name
23553     0x11/imm32/alloc-id:fake
23554     Two-args-float-reg-float-stack/imm32/inouts
23555     0/imm32/no-outputs
23556     0/imm32/no-outputs
23557     0x11/imm32/alloc-id:fake
23558     _string_0f_2f_compare/imm32/subx-name
23559     0/imm32/no-rm32
23560     0/imm32/no-r32
23561     0/imm32/no-imm32
23562     0/imm32/no-imm8
23563     0/imm32/no-disp32
23564     2/imm32/xm32-is-second-inout
23565     1/imm32/x32-is-first-inout
23566     0x11/imm32/alloc-id:fake
23567     _Primitive-break-if-addr</imm32/next
23568 # - branches
23569 _Primitive-break-if-addr<:  # (payload primitive)
23570     0x11/imm32/alloc-id:fake:payload
23571     0x11/imm32/alloc-id:fake
23572     _string-break-if-addr</imm32/name
23573     0/imm32/no-inouts
23574     0/imm32/no-inouts
23575     0/imm32/no-outputs
23576     0/imm32/no-outputs
23577     0x11/imm32/alloc-id:fake
23578     _string_0f_82_jump_break/imm32/subx-name
23579     0/imm32/no-rm32
23580     0/imm32/no-r32
23581     0/imm32/no-imm32
23582     0/imm32/no-imm8
23583     0/imm32/no-disp32
23584     0/imm32/no-xm32
23585     0/imm32/no-x32
23586     0x11/imm32/alloc-id:fake
23587     _Primitive-break-if-addr>=/imm32/next
23588 _Primitive-break-if-addr>=:  # (payload primitive)
23589     0x11/imm32/alloc-id:fake:payload
23590     0x11/imm32/alloc-id:fake
23591     _string-break-if-addr>=/imm32/name
23592     0/imm32/no-inouts
23593     0/imm32/no-inouts
23594     0/imm32/no-outputs
23595     0/imm32/no-outputs
23596     0x11/imm32/alloc-id:fake
23597     _string_0f_83_jump_break/imm32/subx-name
23598     0/imm32/no-rm32
23599     0/imm32/no-r32
23600     0/imm32/no-imm32
23601     0/imm32/no-imm8
23602     0/imm32/no-disp32
23603     0/imm32/no-xm32
23604     0/imm32/no-x32
23605     0x11/imm32/alloc-id:fake
23606     _Primitive-break-if-=/imm32/next
23607 _Primitive-break-if-=:  # (payload primitive)
23608     0x11/imm32/alloc-id:fake:payload
23609     0x11/imm32/alloc-id:fake
23610     _string-break-if-=/imm32/name
23611     0/imm32/no-inouts
23612     0/imm32/no-inouts
23613     0/imm32/no-outputs
23614     0/imm32/no-outputs
23615     0x11/imm32/alloc-id:fake
23616     _string_0f_84_jump_break/imm32/subx-name
23617     0/imm32/no-rm32
23618     0/imm32/no-r32
23619     0/imm32/no-imm32
23620     0/imm32/no-imm8
23621     0/imm32/no-disp32
23622     0/imm32/no-xm32
23623     0/imm32/no-x32
23624     0x11/imm32/alloc-id:fake
23625     _Primitive-break-if-!=/imm32/next
23626 _Primitive-break-if-!=:  # (payload primitive)
23627     0x11/imm32/alloc-id:fake:payload
23628     0x11/imm32/alloc-id:fake
23629     _string-break-if-!=/imm32/name
23630     0/imm32/no-inouts
23631     0/imm32/no-inouts
23632     0/imm32/no-outputs
23633     0/imm32/no-outputs
23634     0x11/imm32/alloc-id:fake
23635     _string_0f_85_jump_break/imm32/subx-name
23636     0/imm32/no-rm32
23637     0/imm32/no-r32
23638     0/imm32/no-imm32
23639     0/imm32/no-imm8
23640     0/imm32/no-disp32
23641     0/imm32/no-xm32
23642     0/imm32/no-x32
23643     0x11/imm32/alloc-id:fake
23644     _Primitive-break-if-addr<=/imm32/next
23645 _Primitive-break-if-addr<=:  # (payload primitive)
23646     0x11/imm32/alloc-id:fake:payload
23647     0x11/imm32/alloc-id:fake
23648     _string-break-if-addr<=/imm32/name
23649     0/imm32/no-inouts
23650     0/imm32/no-inouts
23651     0/imm32/no-outputs
23652     0/imm32/no-outputs
23653     0x11/imm32/alloc-id:fake
23654     _string_0f_86_jump_break/imm32/subx-name
23655     0/imm32/no-rm32
23656     0/imm32/no-r32
23657     0/imm32/no-imm32
23658     0/imm32/no-imm8
23659     0/imm32/no-disp32
23660     0/imm32/no-xm32
23661     0/imm32/no-x32
23662     0x11/imm32/alloc-id:fake
23663     _Primitive-break-if-addr>/imm32/next
23664 _Primitive-break-if-addr>:  # (payload primitive)
23665     0x11/imm32/alloc-id:fake:payload
23666     0x11/imm32/alloc-id:fake
23667     _string-break-if-addr>/imm32/name
23668     0/imm32/no-inouts
23669     0/imm32/no-inouts
23670     0/imm32/no-outputs
23671     0/imm32/no-outputs
23672     0x11/imm32/alloc-id:fake
23673     _string_0f_87_jump_break/imm32/subx-name
23674     0/imm32/no-rm32
23675     0/imm32/no-r32
23676     0/imm32/no-imm32
23677     0/imm32/no-imm8
23678     0/imm32/no-disp32
23679     0/imm32/no-xm32
23680     0/imm32/no-x32
23681     0x11/imm32/alloc-id:fake
23682     _Primitive-break-if-</imm32/next
23683 _Primitive-break-if-<:  # (payload primitive)
23684     0x11/imm32/alloc-id:fake:payload
23685     0x11/imm32/alloc-id:fake
23686     _string-break-if-</imm32/name
23687     0/imm32/no-inouts
23688     0/imm32/no-inouts
23689     0/imm32/no-outputs
23690     0/imm32/no-outputs
23691     0x11/imm32/alloc-id:fake
23692     _string_0f_8c_jump_break/imm32/subx-name
23693     0/imm32/no-rm32
23694     0/imm32/no-r32
23695     0/imm32/no-imm32
23696     0/imm32/no-imm8
23697     0/imm32/no-disp32
23698     0/imm32/no-xm32
23699     0/imm32/no-x32
23700     0x11/imm32/alloc-id:fake
23701     _Primitive-break-if->=/imm32/next
23702 _Primitive-break-if->=:  # (payload primitive)
23703     0x11/imm32/alloc-id:fake:payload
23704     0x11/imm32/alloc-id:fake
23705     _string-break-if->=/imm32/name
23706     0/imm32/no-inouts
23707     0/imm32/no-inouts
23708     0/imm32/no-outputs
23709     0/imm32/no-outputs
23710     0x11/imm32/alloc-id:fake
23711     _string_0f_8d_jump_break/imm32/subx-name
23712     0/imm32/no-rm32
23713     0/imm32/no-r32
23714     0/imm32/no-imm32
23715     0/imm32/no-imm8
23716     0/imm32/no-disp32
23717     0/imm32/no-xm32
23718     0/imm32/no-x32
23719     0x11/imm32/alloc-id:fake
23720     _Primitive-break-if-<=/imm32/next
23721 _Primitive-break-if-<=:  # (payload primitive)
23722     0x11/imm32/alloc-id:fake:payload
23723     0x11/imm32/alloc-id:fake
23724     _string-break-if-<=/imm32/name
23725     0/imm32/no-inouts
23726     0/imm32/no-inouts
23727     0/imm32/no-outputs
23728     0/imm32/no-outputs
23729     0x11/imm32/alloc-id:fake
23730     _string_0f_8e_jump_break/imm32/subx-name
23731     0/imm32/no-rm32
23732     0/imm32/no-r32
23733     0/imm32/no-imm32
23734     0/imm32/no-imm8
23735     0/imm32/no-disp32
23736     0/imm32/no-xm32
23737     0/imm32/no-x32
23738     0x11/imm32/alloc-id:fake
23739     _Primitive-break-if->/imm32/next
23740 _Primitive-break-if->:  # (payload primitive)
23741     0x11/imm32/alloc-id:fake:payload
23742     0x11/imm32/alloc-id:fake
23743     _string-break-if->/imm32/name
23744     0/imm32/no-inouts
23745     0/imm32/no-inouts
23746     0/imm32/no-outputs
23747     0/imm32/no-outputs
23748     0x11/imm32/alloc-id:fake
23749     _string_0f_8f_jump_break/imm32/subx-name
23750     0/imm32/no-rm32
23751     0/imm32/no-r32
23752     0/imm32/no-imm32
23753     0/imm32/no-imm8
23754     0/imm32/no-disp32
23755     0/imm32/no-xm32
23756     0/imm32/no-x32
23757     0x11/imm32/alloc-id:fake
23758     _Primitive-break/imm32/next
23759 _Primitive-break:  # (payload primitive)
23760     0x11/imm32/alloc-id:fake:payload
23761     0x11/imm32/alloc-id:fake
23762     _string-break/imm32/name
23763     0/imm32/no-inouts
23764     0/imm32/no-inouts
23765     0/imm32/no-outputs
23766     0/imm32/no-outputs
23767     0x11/imm32/alloc-id:fake
23768     _string_e9_jump_break/imm32/subx-name
23769     0/imm32/no-rm32
23770     0/imm32/no-r32
23771     0/imm32/no-imm32
23772     0/imm32/no-imm8
23773     0/imm32/no-disp32
23774     0/imm32/no-xm32
23775     0/imm32/no-x32
23776     0x11/imm32/alloc-id:fake
23777     _Primitive-loop-if-addr</imm32/next
23778 _Primitive-loop-if-addr<:  # (payload primitive)
23779     0x11/imm32/alloc-id:fake:payload
23780     0x11/imm32/alloc-id:fake
23781     _string-loop-if-addr</imm32/name
23782     0/imm32/no-inouts
23783     0/imm32/no-inouts
23784     0/imm32/no-outputs
23785     0/imm32/no-outputs
23786     0x11/imm32/alloc-id:fake
23787     _string_0f_82_jump_loop/imm32/subx-name
23788     0/imm32/no-rm32
23789     0/imm32/no-r32
23790     0/imm32/no-imm32
23791     0/imm32/no-imm8
23792     0/imm32/no-disp32
23793     0/imm32/no-xm32
23794     0/imm32/no-x32
23795     0x11/imm32/alloc-id:fake
23796     _Primitive-loop-if-addr>=/imm32/next
23797 _Primitive-loop-if-addr>=:  # (payload primitive)
23798     0x11/imm32/alloc-id:fake:payload
23799     0x11/imm32/alloc-id:fake
23800     _string-loop-if-addr>=/imm32/name
23801     0/imm32/no-inouts
23802     0/imm32/no-inouts
23803     0/imm32/no-outputs
23804     0/imm32/no-outputs
23805     0x11/imm32/alloc-id:fake
23806     _string_0f_83_jump_loop/imm32/subx-name
23807     0/imm32/no-rm32
23808     0/imm32/no-r32
23809     0/imm32/no-imm32
23810     0/imm32/no-imm8
23811     0/imm32/no-disp32
23812     0/imm32/no-xm32
23813     0/imm32/no-x32
23814     0x11/imm32/alloc-id:fake
23815     _Primitive-loop-if-=/imm32/next
23816 _Primitive-loop-if-=:  # (payload primitive)
23817     0x11/imm32/alloc-id:fake:payload
23818     0x11/imm32/alloc-id:fake
23819     _string-loop-if-=/imm32/name
23820     0/imm32/no-inouts
23821     0/imm32/no-inouts
23822     0/imm32/no-outputs
23823     0/imm32/no-outputs
23824     0x11/imm32/alloc-id:fake
23825     _string_0f_84_jump_loop/imm32/subx-name
23826     0/imm32/no-rm32
23827     0/imm32/no-r32
23828     0/imm32/no-imm32
23829     0/imm32/no-imm8
23830     0/imm32/no-disp32
23831     0/imm32/no-xm32
23832     0/imm32/no-x32
23833     0x11/imm32/alloc-id:fake
23834     _Primitive-loop-if-!=/imm32/next
23835 _Primitive-loop-if-!=:  # (payload primitive)
23836     0x11/imm32/alloc-id:fake:payload
23837     0x11/imm32/alloc-id:fake
23838     _string-loop-if-!=/imm32/name
23839     0/imm32/no-inouts
23840     0/imm32/no-inouts
23841     0/imm32/no-outputs
23842     0/imm32/no-outputs
23843     0x11/imm32/alloc-id:fake
23844     _string_0f_85_jump_loop/imm32/subx-name
23845     0/imm32/no-rm32
23846     0/imm32/no-r32
23847     0/imm32/no-imm32
23848     0/imm32/no-imm8
23849     0/imm32/no-disp32
23850     0/imm32/no-xm32
23851     0/imm32/no-x32
23852     0x11/imm32/alloc-id:fake
23853     _Primitive-loop-if-addr<=/imm32/next
23854 _Primitive-loop-if-addr<=:  # (payload primitive)
23855     0x11/imm32/alloc-id:fake:payload
23856     0x11/imm32/alloc-id:fake
23857     _string-loop-if-addr<=/imm32/name
23858     0/imm32/no-inouts
23859     0/imm32/no-inouts
23860     0/imm32/no-outputs
23861     0/imm32/no-outputs
23862     0x11/imm32/alloc-id:fake
23863     _string_0f_86_jump_loop/imm32/subx-name
23864     0/imm32/no-rm32
23865     0/imm32/no-r32
23866     0/imm32/no-imm32
23867     0/imm32/no-imm8
23868     0/imm32/no-disp32
23869     0/imm32/no-xm32
23870     0/imm32/no-x32
23871     0x11/imm32/alloc-id:fake
23872     _Primitive-loop-if-addr>/imm32/next
23873 _Primitive-loop-if-addr>:  # (payload primitive)
23874     0x11/imm32/alloc-id:fake:payload
23875     0x11/imm32/alloc-id:fake
23876     _string-loop-if-addr>/imm32/name
23877     0/imm32/no-inouts
23878     0/imm32/no-inouts
23879     0/imm32/no-outputs
23880     0/imm32/no-outputs
23881     0x11/imm32/alloc-id:fake
23882     _string_0f_87_jump_loop/imm32/subx-name
23883     0/imm32/no-rm32
23884     0/imm32/no-r32
23885     0/imm32/no-imm32
23886     0/imm32/no-imm8
23887     0/imm32/no-disp32
23888     0/imm32/no-xm32
23889     0/imm32/no-x32
23890     0x11/imm32/alloc-id:fake
23891     _Primitive-loop-if-</imm32/next
23892 _Primitive-loop-if-<:  # (payload primitive)
23893     0x11/imm32/alloc-id:fake:payload
23894     0x11/imm32/alloc-id:fake
23895     _string-loop-if-</imm32/name
23896     0/imm32/no-inouts
23897     0/imm32/no-inouts
23898     0/imm32/no-outputs
23899     0/imm32/no-outputs
23900     0x11/imm32/alloc-id:fake
23901     _string_0f_8c_jump_loop/imm32/subx-name
23902     0/imm32/no-rm32
23903     0/imm32/no-r32
23904     0/imm32/no-imm32
23905     0/imm32/no-imm8
23906     0/imm32/no-disp32
23907     0/imm32/no-xm32
23908     0/imm32/no-x32
23909     0x11/imm32/alloc-id:fake
23910     _Primitive-loop-if->=/imm32/next
23911 _Primitive-loop-if->=:  # (payload primitive)
23912     0x11/imm32/alloc-id:fake:payload
23913     0x11/imm32/alloc-id:fake
23914     _string-loop-if->=/imm32/name
23915     0/imm32/no-inouts
23916     0/imm32/no-inouts
23917     0/imm32/no-outputs
23918     0/imm32/no-outputs
23919     0x11/imm32/alloc-id:fake
23920     _string_0f_8d_jump_loop/imm32/subx-name
23921     0/imm32/no-rm32
23922     0/imm32/no-r32
23923     0/imm32/no-imm32
23924     0/imm32/no-imm8
23925     0/imm32/no-disp32
23926     0/imm32/no-xm32
23927     0/imm32/no-x32
23928     0x11/imm32/alloc-id:fake
23929     _Primitive-loop-if-<=/imm32/next
23930 _Primitive-loop-if-<=:  # (payload primitive)
23931     0x11/imm32/alloc-id:fake:payload
23932     0x11/imm32/alloc-id:fake
23933     _string-loop-if-<=/imm32/name
23934     0/imm32/no-inouts
23935     0/imm32/no-inouts
23936     0/imm32/no-outputs
23937     0/imm32/no-outputs
23938     0x11/imm32/alloc-id:fake
23939     _string_0f_8e_jump_loop/imm32/subx-name
23940     0/imm32/no-rm32
23941     0/imm32/no-r32
23942     0/imm32/no-imm32
23943     0/imm32/no-imm8
23944     0/imm32/no-disp32
23945     0/imm32/no-xm32
23946     0/imm32/no-x32
23947     0x11/imm32/alloc-id:fake
23948     _Primitive-loop-if->/imm32/next
23949 _Primitive-loop-if->:  # (payload primitive)
23950     0x11/imm32/alloc-id:fake:payload
23951     0x11/imm32/alloc-id:fake
23952     _string-loop-if->/imm32/name
23953     0/imm32/no-inouts
23954     0/imm32/no-inouts
23955     0/imm32/no-outputs
23956     0/imm32/no-outputs
23957     0x11/imm32/alloc-id:fake
23958     _string_0f_8f_jump_loop/imm32/subx-name
23959     0/imm32/no-rm32
23960     0/imm32/no-r32
23961     0/imm32/no-imm32
23962     0/imm32/no-imm8
23963     0/imm32/no-disp32
23964     0/imm32/no-xm32
23965     0/imm32/no-x32
23966     0x11/imm32/alloc-id:fake
23967     _Primitive-loop/imm32/next  # we probably don't need an unconditional break
23968 _Primitive-loop:  # (payload primitive)
23969     0x11/imm32/alloc-id:fake:payload
23970     0x11/imm32/alloc-id:fake
23971     _string-loop/imm32/name
23972     0/imm32/no-inouts
23973     0/imm32/no-inouts
23974     0/imm32/no-outputs
23975     0/imm32/no-outputs
23976     0x11/imm32/alloc-id:fake
23977     _string_e9_jump_loop/imm32/subx-name
23978     0/imm32/no-rm32
23979     0/imm32/no-r32
23980     0/imm32/no-imm32
23981     0/imm32/no-imm8
23982     0/imm32/no-disp32
23983     0/imm32/no-xm32
23984     0/imm32/no-x32
23985     0x11/imm32/alloc-id:fake
23986     _Primitive-break-if-addr<-named/imm32/next
23987 # - branches to named blocks
23988 _Primitive-break-if-addr<-named:  # (payload primitive)
23989     0x11/imm32/alloc-id:fake:payload
23990     0x11/imm32/alloc-id:fake
23991     _string-break-if-addr</imm32/name
23992     0x11/imm32/alloc-id:fake
23993     Single-lit-var/imm32/inouts
23994     0/imm32/no-outputs
23995     0/imm32/no-outputs
23996     0x11/imm32/alloc-id:fake
23997     _string_0f_82_jump_label/imm32/subx-name
23998     0/imm32/no-rm32
23999     0/imm32/no-r32
24000     0/imm32/no-imm32
24001     0/imm32/no-imm8
24002     1/imm32/disp32-is-first-inout
24003     0/imm32/no-xm32
24004     0/imm32/no-x32
24005     0x11/imm32/alloc-id:fake
24006     _Primitive-break-if-addr>=-named/imm32/next
24007 _Primitive-break-if-addr>=-named:  # (payload primitive)
24008     0x11/imm32/alloc-id:fake:payload
24009     0x11/imm32/alloc-id:fake
24010     _string-break-if-addr>=/imm32/name
24011     0x11/imm32/alloc-id:fake
24012     Single-lit-var/imm32/inouts
24013     0/imm32/no-outputs
24014     0/imm32/no-outputs
24015     0x11/imm32/alloc-id:fake
24016     _string_0f_83_jump_label/imm32/subx-name
24017     0/imm32/no-rm32
24018     0/imm32/no-r32
24019     0/imm32/no-imm32
24020     0/imm32/no-imm8
24021     1/imm32/disp32-is-first-inout
24022     0/imm32/no-xm32
24023     0/imm32/no-x32
24024     0x11/imm32/alloc-id:fake
24025     _Primitive-break-if-=-named/imm32/next
24026 _Primitive-break-if-=-named:  # (payload primitive)
24027     0x11/imm32/alloc-id:fake:payload
24028     0x11/imm32/alloc-id:fake
24029     _string-break-if-=/imm32/name
24030     0x11/imm32/alloc-id:fake
24031     Single-lit-var/imm32/inouts
24032     0/imm32/no-outputs
24033     0/imm32/no-outputs
24034     0x11/imm32/alloc-id:fake
24035     _string_0f_84_jump_label/imm32/subx-name
24036     0/imm32/no-rm32
24037     0/imm32/no-r32
24038     0/imm32/no-imm32
24039     0/imm32/no-imm8
24040     1/imm32/disp32-is-first-inout
24041     0/imm32/no-xm32
24042     0/imm32/no-x32
24043     0x11/imm32/alloc-id:fake
24044     _Primitive-break-if-!=-named/imm32/next
24045 _Primitive-break-if-!=-named:  # (payload primitive)
24046     0x11/imm32/alloc-id:fake:payload
24047     0x11/imm32/alloc-id:fake
24048     _string-break-if-!=/imm32/name
24049     0x11/imm32/alloc-id:fake
24050     Single-lit-var/imm32/inouts
24051     0/imm32/no-outputs
24052     0/imm32/no-outputs
24053     0x11/imm32/alloc-id:fake
24054     _string_0f_85_jump_label/imm32/subx-name
24055     0/imm32/no-rm32
24056     0/imm32/no-r32
24057     0/imm32/no-imm32
24058     0/imm32/no-imm8
24059     1/imm32/disp32-is-first-inout
24060     0/imm32/no-xm32
24061     0/imm32/no-x32
24062     0x11/imm32/alloc-id:fake
24063     _Primitive-break-if-addr<=-named/imm32/next
24064 _Primitive-break-if-addr<=-named:  # (payload primitive)
24065     0x11/imm32/alloc-id:fake:payload
24066     0x11/imm32/alloc-id:fake
24067     _string-break-if-addr<=/imm32/name
24068     0x11/imm32/alloc-id:fake
24069     Single-lit-var/imm32/inouts
24070     0/imm32/no-outputs
24071     0/imm32/no-outputs
24072     0x11/imm32/alloc-id:fake
24073     _string_0f_86_jump_label/imm32/subx-name
24074     0/imm32/no-rm32
24075     0/imm32/no-r32
24076     0/imm32/no-imm32
24077     0/imm32/no-imm8
24078     1/imm32/disp32-is-first-inout
24079     0/imm32/no-xm32
24080     0/imm32/no-x32
24081     0x11/imm32/alloc-id:fake
24082     _Primitive-break-if-addr>-named/imm32/next
24083 _Primitive-break-if-addr>-named:  # (payload primitive)
24084     0x11/imm32/alloc-id:fake:payload
24085     0x11/imm32/alloc-id:fake
24086     _string-break-if-addr>/imm32/name
24087     0x11/imm32/alloc-id:fake
24088     Single-lit-var/imm32/inouts
24089     0/imm32/no-outputs
24090     0/imm32/no-outputs
24091     0x11/imm32/alloc-id:fake
24092     _string_0f_87_jump_label/imm32/subx-name
24093     0/imm32/no-rm32
24094     0/imm32/no-r32
24095     0/imm32/no-imm32
24096     0/imm32/no-imm8
24097     1/imm32/disp32-is-first-inout
24098     0/imm32/no-xm32
24099     0/imm32/no-x32
24100     0x11/imm32/alloc-id:fake
24101     _Primitive-break-if-<-named/imm32/next
24102 _Primitive-break-if-<-named:  # (payload primitive)
24103     0x11/imm32/alloc-id:fake:payload
24104     0x11/imm32/alloc-id:fake
24105     _string-break-if-</imm32/name
24106     0x11/imm32/alloc-id:fake
24107     Single-lit-var/imm32/inouts
24108     0/imm32/no-outputs
24109     0/imm32/no-outputs
24110     0x11/imm32/alloc-id:fake
24111     _string_0f_8c_jump_label/imm32/subx-name
24112     0/imm32/no-rm32
24113     0/imm32/no-r32
24114     0/imm32/no-imm32
24115     0/imm32/no-imm8
24116     1/imm32/disp32-is-first-inout
24117     0/imm32/no-xm32
24118     0/imm32/no-x32
24119     0x11/imm32/alloc-id:fake
24120     _Primitive-break-if->=-named/imm32/next
24121 _Primitive-break-if->=-named:  # (payload primitive)
24122     0x11/imm32/alloc-id:fake:payload
24123     0x11/imm32/alloc-id:fake
24124     _string-break-if->=/imm32/name
24125     0x11/imm32/alloc-id:fake
24126     Single-lit-var/imm32/inouts
24127     0/imm32/no-outputs
24128     0/imm32/no-outputs
24129     0x11/imm32/alloc-id:fake
24130     _string_0f_8d_jump_label/imm32/subx-name
24131     0/imm32/no-rm32
24132     0/imm32/no-r32
24133     0/imm32/no-imm32
24134     0/imm32/no-imm8
24135     1/imm32/disp32-is-first-inout
24136     0/imm32/no-xm32
24137     0/imm32/no-x32
24138     0x11/imm32/alloc-id:fake
24139     _Primitive-break-if-<=-named/imm32/next
24140 _Primitive-break-if-<=-named:  # (payload primitive)
24141     0x11/imm32/alloc-id:fake:payload
24142     0x11/imm32/alloc-id:fake
24143     _string-break-if-<=/imm32/name
24144     0x11/imm32/alloc-id:fake
24145     Single-lit-var/imm32/inouts
24146     0/imm32/no-outputs
24147     0/imm32/no-outputs
24148     0x11/imm32/alloc-id:fake
24149     _string_0f_8e_jump_label/imm32/subx-name
24150     0/imm32/no-rm32
24151     0/imm32/no-r32
24152     0/imm32/no-imm32
24153     0/imm32/no-imm8
24154     1/imm32/disp32-is-first-inout
24155     0/imm32/no-xm32
24156     0/imm32/no-x32
24157     0x11/imm32/alloc-id:fake
24158     _Primitive-break-if->-named/imm32/next
24159 _Primitive-break-if->-named:  # (payload primitive)
24160     0x11/imm32/alloc-id:fake:payload
24161     0x11/imm32/alloc-id:fake
24162     _string-break-if->/imm32/name
24163     0x11/imm32/alloc-id:fake
24164     Single-lit-var/imm32/inouts
24165     0/imm32/no-outputs
24166     0/imm32/no-outputs
24167     0x11/imm32/alloc-id:fake
24168     _string_0f_8f_jump_label/imm32/subx-name
24169     0/imm32/no-rm32
24170     0/imm32/no-r32
24171     0/imm32/no-imm32
24172     0/imm32/no-imm8
24173     1/imm32/disp32-is-first-inout
24174     0/imm32/no-xm32
24175     0/imm32/no-x32
24176     0x11/imm32/alloc-id:fake
24177     _Primitive-break-named/imm32/next
24178 _Primitive-break-named:  # (payload primitive)
24179     0x11/imm32/alloc-id:fake:payload
24180     0x11/imm32/alloc-id:fake
24181     _string-break/imm32/name
24182     0x11/imm32/alloc-id:fake
24183     Single-lit-var/imm32/inouts
24184     0/imm32/no-outputs
24185     0/imm32/no-outputs
24186     0x11/imm32/alloc-id:fake
24187     _string_e9_jump_label/imm32/subx-name
24188     0/imm32/no-rm32
24189     0/imm32/no-r32
24190     0/imm32/no-imm32
24191     0/imm32/no-imm8
24192     1/imm32/disp32-is-first-inout
24193     0/imm32/no-xm32
24194     0/imm32/no-x32
24195     0x11/imm32/alloc-id:fake
24196     _Primitive-loop-if-addr<-named/imm32/next
24197 _Primitive-loop-if-addr<-named:  # (payload primitive)
24198     0x11/imm32/alloc-id:fake:payload
24199     0x11/imm32/alloc-id:fake
24200     _string-loop-if-addr</imm32/name
24201     0x11/imm32/alloc-id:fake
24202     Single-lit-var/imm32/inouts
24203     0/imm32/no-outputs
24204     0/imm32/no-outputs
24205     0x11/imm32/alloc-id:fake
24206     _string_0f_82_jump_label/imm32/subx-name
24207     0/imm32/no-rm32
24208     0/imm32/no-r32
24209     0/imm32/no-imm32
24210     0/imm32/no-imm8
24211     1/imm32/disp32-is-first-inout
24212     0/imm32/no-xm32
24213     0/imm32/no-x32
24214     0x11/imm32/alloc-id:fake
24215     _Primitive-loop-if-addr>=-named/imm32/next
24216 _Primitive-loop-if-addr>=-named:  # (payload primitive)
24217     0x11/imm32/alloc-id:fake:payload
24218     0x11/imm32/alloc-id:fake
24219     _string-loop-if-addr>=/imm32/name
24220     0x11/imm32/alloc-id:fake
24221     Single-lit-var/imm32/inouts
24222     0/imm32/no-outputs
24223     0/imm32/no-outputs
24224     0x11/imm32/alloc-id:fake
24225     _string_0f_83_jump_label/imm32/subx-name
24226     0/imm32/no-rm32
24227     0/imm32/no-r32
24228     0/imm32/no-imm32
24229     0/imm32/no-imm8
24230     1/imm32/disp32-is-first-inout
24231     0/imm32/no-xm32
24232     0/imm32/no-x32
24233     0x11/imm32/alloc-id:fake
24234     _Primitive-loop-if-=-named/imm32/next
24235 _Primitive-loop-if-=-named:  # (payload primitive)
24236     0x11/imm32/alloc-id:fake:payload
24237     0x11/imm32/alloc-id:fake
24238     _string-loop-if-=/imm32/name
24239     0x11/imm32/alloc-id:fake
24240     Single-lit-var/imm32/inouts
24241     0/imm32/no-outputs
24242     0/imm32/no-outputs
24243     0x11/imm32/alloc-id:fake
24244     _string_0f_84_jump_label/imm32/subx-name
24245     0/imm32/no-rm32
24246     0/imm32/no-r32
24247     0/imm32/no-imm32
24248     0/imm32/no-imm8
24249     1/imm32/disp32-is-first-inout
24250     0/imm32/no-xm32
24251     0/imm32/no-x32
24252     0x11/imm32/alloc-id:fake
24253     _Primitive-loop-if-!=-named/imm32/next
24254 _Primitive-loop-if-!=-named:  # (payload primitive)
24255     0x11/imm32/alloc-id:fake:payload
24256     0x11/imm32/alloc-id:fake
24257     _string-loop-if-!=/imm32/name
24258     0x11/imm32/alloc-id:fake
24259     Single-lit-var/imm32/inouts
24260     0/imm32/no-outputs
24261     0/imm32/no-outputs
24262     0x11/imm32/alloc-id:fake
24263     _string_0f_85_jump_label/imm32/subx-name
24264     0/imm32/no-rm32
24265     0/imm32/no-r32
24266     0/imm32/no-imm32
24267     0/imm32/no-imm8
24268     1/imm32/disp32-is-first-inout
24269     0/imm32/no-xm32
24270     0/imm32/no-x32
24271     0x11/imm32/alloc-id:fake
24272     _Primitive-loop-if-addr<=-named/imm32/next
24273 _Primitive-loop-if-addr<=-named:  # (payload primitive)
24274     0x11/imm32/alloc-id:fake:payload
24275     0x11/imm32/alloc-id:fake
24276     _string-loop-if-addr<=/imm32/name
24277     0x11/imm32/alloc-id:fake
24278     Single-lit-var/imm32/inouts
24279     0/imm32/no-outputs
24280     0/imm32/no-outputs
24281     0x11/imm32/alloc-id:fake
24282     _string_0f_86_jump_label/imm32/subx-name
24283     0/imm32/no-rm32
24284     0/imm32/no-r32
24285     0/imm32/no-imm32
24286     0/imm32/no-imm8
24287     1/imm32/disp32-is-first-inout
24288     0/imm32/no-xm32
24289     0/imm32/no-x32
24290     0x11/imm32/alloc-id:fake
24291     _Primitive-loop-if-addr>-named/imm32/next
24292 _Primitive-loop-if-addr>-named:  # (payload primitive)
24293     0x11/imm32/alloc-id:fake:payload
24294     0x11/imm32/alloc-id:fake
24295     _string-loop-if-addr>/imm32/name
24296     0x11/imm32/alloc-id:fake
24297     Single-lit-var/imm32/inouts
24298     0/imm32/no-outputs
24299     0/imm32/no-outputs
24300     0x11/imm32/alloc-id:fake
24301     _string_0f_87_jump_label/imm32/subx-name
24302     0/imm32/no-rm32
24303     0/imm32/no-r32
24304     0/imm32/no-imm32
24305     0/imm32/no-imm8
24306     1/imm32/disp32-is-first-inout
24307     0/imm32/no-xm32
24308     0/imm32/no-x32
24309     0x11/imm32/alloc-id:fake
24310     _Primitive-loop-if-<-named/imm32/next
24311 _Primitive-loop-if-<-named:  # (payload primitive)
24312     0x11/imm32/alloc-id:fake:payload
24313     0x11/imm32/alloc-id:fake
24314     _string-loop-if-</imm32/name
24315     0x11/imm32/alloc-id:fake
24316     Single-lit-var/imm32/inouts
24317     0/imm32/no-outputs
24318     0/imm32/no-outputs
24319     0x11/imm32/alloc-id:fake
24320     _string_0f_8c_jump_label/imm32/subx-name
24321     0/imm32/no-rm32
24322     0/imm32/no-r32
24323     0/imm32/no-imm32
24324     0/imm32/no-imm8
24325     1/imm32/disp32-is-first-inout
24326     0/imm32/no-xm32
24327     0/imm32/no-x32
24328     0x11/imm32/alloc-id:fake
24329     _Primitive-loop-if->=-named/imm32/next
24330 _Primitive-loop-if->=-named:  # (payload primitive)
24331     0x11/imm32/alloc-id:fake:payload
24332     0x11/imm32/alloc-id:fake
24333     _string-loop-if->=/imm32/name
24334     0x11/imm32/alloc-id:fake
24335     Single-lit-var/imm32/inouts
24336     0/imm32/no-outputs
24337     0/imm32/no-outputs
24338     0x11/imm32/alloc-id:fake
24339     _string_0f_8d_jump_label/imm32/subx-name
24340     0/imm32/no-rm32
24341     0/imm32/no-r32
24342     0/imm32/no-imm32
24343     0/imm32/no-imm8
24344     1/imm32/disp32-is-first-inout
24345     0/imm32/no-xm32
24346     0/imm32/no-x32
24347     0x11/imm32/alloc-id:fake
24348     _Primitive-loop-if-<=-named/imm32/next
24349 _Primitive-loop-if-<=-named:  # (payload primitive)
24350     0x11/imm32/alloc-id:fake:payload
24351     0x11/imm32/alloc-id:fake
24352     _string-loop-if-<=/imm32/name
24353     0x11/imm32/alloc-id:fake
24354     Single-lit-var/imm32/inouts
24355     0/imm32/no-outputs
24356     0/imm32/no-outputs
24357     0x11/imm32/alloc-id:fake
24358     _string_0f_8e_jump_label/imm32/subx-name
24359     0/imm32/no-rm32
24360     0/imm32/no-r32
24361     0/imm32/no-imm32
24362     0/imm32/no-imm8
24363     1/imm32/disp32-is-first-inout
24364     0/imm32/no-xm32
24365     0/imm32/no-x32
24366     0x11/imm32/alloc-id:fake
24367     _Primitive-loop-if->-named/imm32/next
24368 _Primitive-loop-if->-named:  # (payload primitive)
24369     0x11/imm32/alloc-id:fake:payload
24370     0x11/imm32/alloc-id:fake
24371     _string-loop-if->/imm32/name
24372     0x11/imm32/alloc-id:fake
24373     Single-lit-var/imm32/inouts
24374     0/imm32/no-outputs
24375     0/imm32/no-outputs
24376     0x11/imm32/alloc-id:fake
24377     _string_0f_8f_jump_label/imm32/subx-name
24378     0/imm32/no-rm32
24379     0/imm32/no-r32
24380     0/imm32/no-imm32
24381     0/imm32/no-imm8
24382     1/imm32/disp32-is-first-inout
24383     0/imm32/no-xm32
24384     0/imm32/no-x32
24385     0x11/imm32/alloc-id:fake
24386     _Primitive-loop-named/imm32/next  # we probably don't need an unconditional break
24387 _Primitive-loop-named:  # (payload primitive)
24388     0x11/imm32/alloc-id:fake:payload
24389     0x11/imm32/alloc-id:fake
24390     _string-loop/imm32/name
24391     0x11/imm32/alloc-id:fake
24392     Single-lit-var/imm32/inouts
24393     0/imm32/no-outputs
24394     0/imm32/no-outputs
24395     0x11/imm32/alloc-id:fake
24396     _string_e9_jump_label/imm32/subx-name
24397     0/imm32/no-rm32
24398     0/imm32/no-r32
24399     0/imm32/no-imm32
24400     0/imm32/no-imm8
24401     1/imm32/disp32-is-first-inout
24402     0/imm32/no-xm32
24403     0/imm32/no-x32
24404     0x11/imm32/alloc-id:fake
24405     _Primitive-break-if-float</imm32/next
24406 # - branches based on floating-point comparisons
24407 _Primitive-break-if-float<:  # (payload primitive)
24408     0x11/imm32/alloc-id:fake:payload
24409     0x11/imm32/alloc-id:fake
24410     _string-break-if-float</imm32/name
24411     0/imm32/no-inouts
24412     0/imm32/no-inouts
24413     0/imm32/no-outputs
24414     0/imm32/no-outputs
24415     0x11/imm32/alloc-id:fake
24416     _string_0f_82_jump_break/imm32/subx-name
24417     0/imm32/no-rm32
24418     0/imm32/no-r32
24419     0/imm32/no-imm32
24420     0/imm32/no-imm8
24421     0/imm32/no-disp32
24422     0/imm32/no-xm32
24423     0/imm32/no-x32
24424     0x11/imm32/alloc-id:fake
24425     _Primitive-break-if-float>=/imm32/next
24426 _Primitive-break-if-float>=:  # (payload primitive)
24427     0x11/imm32/alloc-id:fake:payload
24428     0x11/imm32/alloc-id:fake
24429     _string-break-if-float>=/imm32/name
24430     0/imm32/no-inouts
24431     0/imm32/no-inouts
24432     0/imm32/no-outputs
24433     0/imm32/no-outputs
24434     0x11/imm32/alloc-id:fake
24435     _string_0f_83_jump_break/imm32/subx-name
24436     0/imm32/no-rm32
24437     0/imm32/no-r32
24438     0/imm32/no-imm32
24439     0/imm32/no-imm8
24440     0/imm32/no-disp32
24441     0/imm32/no-xm32
24442     0/imm32/no-x32
24443     0x11/imm32/alloc-id:fake
24444     _Primitive-break-if-float<=/imm32/next
24445 _Primitive-break-if-float<=:  # (payload primitive)
24446     0x11/imm32/alloc-id:fake:payload
24447     0x11/imm32/alloc-id:fake
24448     _string-break-if-float<=/imm32/name
24449     0/imm32/no-inouts
24450     0/imm32/no-inouts
24451     0/imm32/no-outputs
24452     0/imm32/no-outputs
24453     0x11/imm32/alloc-id:fake
24454     _string_0f_86_jump_break/imm32/subx-name
24455     0/imm32/no-rm32
24456     0/imm32/no-r32
24457     0/imm32/no-imm32
24458     0/imm32/no-imm8
24459     0/imm32/no-disp32
24460     0/imm32/no-xm32
24461     0/imm32/no-x32
24462     0x11/imm32/alloc-id:fake
24463     _Primitive-break-if-float>/imm32/next
24464 _Primitive-break-if-float>:  # (payload primitive)
24465     0x11/imm32/alloc-id:fake:payload
24466     0x11/imm32/alloc-id:fake
24467     _string-break-if-float>/imm32/name
24468     0/imm32/no-inouts
24469     0/imm32/no-inouts
24470     0/imm32/no-outputs
24471     0/imm32/no-outputs
24472     0x11/imm32/alloc-id:fake
24473     _string_0f_87_jump_break/imm32/subx-name
24474     0/imm32/no-rm32
24475     0/imm32/no-r32
24476     0/imm32/no-imm32
24477     0/imm32/no-imm8
24478     0/imm32/no-disp32
24479     0/imm32/no-xm32
24480     0/imm32/no-x32
24481     0x11/imm32/alloc-id:fake
24482     _Primitive-loop-if-float</imm32/next
24483 _Primitive-loop-if-float<:  # (payload primitive)
24484     0x11/imm32/alloc-id:fake:payload
24485     0x11/imm32/alloc-id:fake
24486     _string-loop-if-float</imm32/name
24487     0/imm32/no-inouts
24488     0/imm32/no-inouts
24489     0/imm32/no-outputs
24490     0/imm32/no-outputs
24491     0x11/imm32/alloc-id:fake
24492     _string_0f_82_jump_loop/imm32/subx-name
24493     0/imm32/no-rm32
24494     0/imm32/no-r32
24495     0/imm32/no-imm32
24496     0/imm32/no-imm8
24497     0/imm32/no-disp32
24498     0/imm32/no-xm32
24499     0/imm32/no-x32
24500     0x11/imm32/alloc-id:fake
24501     _Primitive-loop-if-float>=/imm32/next
24502 _Primitive-loop-if-float>=:  # (payload primitive)
24503     0x11/imm32/alloc-id:fake:payload
24504     0x11/imm32/alloc-id:fake
24505     _string-loop-if-float>=/imm32/name
24506     0/imm32/no-inouts
24507     0/imm32/no-inouts
24508     0/imm32/no-outputs
24509     0/imm32/no-outputs
24510     0x11/imm32/alloc-id:fake
24511     _string_0f_83_jump_loop/imm32/subx-name
24512     0/imm32/no-rm32
24513     0/imm32/no-r32
24514     0/imm32/no-imm32
24515     0/imm32/no-imm8
24516     0/imm32/no-disp32
24517     0/imm32/no-xm32
24518     0/imm32/no-x32
24519     0x11/imm32/alloc-id:fake
24520     _Primitive-loop-if-float<=/imm32/next
24521 _Primitive-loop-if-float<=:  # (payload primitive)
24522     0x11/imm32/alloc-id:fake:payload
24523     0x11/imm32/alloc-id:fake
24524     _string-loop-if-float<=/imm32/name
24525     0/imm32/no-inouts
24526     0/imm32/no-inouts
24527     0/imm32/no-outputs
24528     0/imm32/no-outputs
24529     0x11/imm32/alloc-id:fake
24530     _string_0f_86_jump_loop/imm32/subx-name
24531     0/imm32/no-rm32
24532     0/imm32/no-r32
24533     0/imm32/no-imm32
24534     0/imm32/no-imm8
24535     0/imm32/no-disp32
24536     0/imm32/no-xm32
24537     0/imm32/no-x32
24538     0x11/imm32/alloc-id:fake
24539     _Primitive-loop-if-float>/imm32/next
24540 _Primitive-loop-if-float>:  # (payload primitive)
24541     0x11/imm32/alloc-id:fake:payload
24542     0x11/imm32/alloc-id:fake
24543     _string-loop-if-float>/imm32/name
24544     0/imm32/no-inouts
24545     0/imm32/no-inouts
24546     0/imm32/no-outputs
24547     0/imm32/no-outputs
24548     0x11/imm32/alloc-id:fake
24549     _string_0f_87_jump_loop/imm32/subx-name
24550     0/imm32/no-rm32
24551     0/imm32/no-r32
24552     0/imm32/no-imm32
24553     0/imm32/no-imm8
24554     0/imm32/no-disp32
24555     0/imm32/no-xm32
24556     0/imm32/no-x32
24557     0x11/imm32/alloc-id:fake
24558     _Primitive-break-if-float<-named/imm32/next
24559 _Primitive-break-if-float<-named:  # (payload primitive)
24560     0x11/imm32/alloc-id:fake:payload
24561     0x11/imm32/alloc-id:fake
24562     _string-break-if-float</imm32/name
24563     0x11/imm32/alloc-id:fake
24564     Single-lit-var/imm32/inouts
24565     0/imm32/no-outputs
24566     0/imm32/no-outputs
24567     0x11/imm32/alloc-id:fake
24568     _string_0f_82_jump_label/imm32/subx-name
24569     0/imm32/no-rm32
24570     0/imm32/no-r32
24571     0/imm32/no-imm32
24572     0/imm32/no-imm8
24573     1/imm32/disp32-is-first-inout
24574     0/imm32/no-xm32
24575     0/imm32/no-x32
24576     0x11/imm32/alloc-id:fake
24577     _Primitive-break-if-float>=-named/imm32/next
24578 _Primitive-break-if-float>=-named:  # (payload primitive)
24579     0x11/imm32/alloc-id:fake:payload
24580     0x11/imm32/alloc-id:fake
24581     _string-break-if-float>=/imm32/name
24582     0x11/imm32/alloc-id:fake
24583     Single-lit-var/imm32/inouts
24584     0/imm32/no-outputs
24585     0/imm32/no-outputs
24586     0x11/imm32/alloc-id:fake
24587     _string_0f_83_jump_label/imm32/subx-name
24588     0/imm32/no-rm32
24589     0/imm32/no-r32
24590     0/imm32/no-imm32
24591     0/imm32/no-imm8
24592     1/imm32/disp32-is-first-inout
24593     0/imm32/no-xm32
24594     0/imm32/no-x32
24595     0x11/imm32/alloc-id:fake
24596     _Primitive-break-if-float<=-named/imm32/next
24597 _Primitive-break-if-float<=-named:  # (payload primitive)
24598     0x11/imm32/alloc-id:fake:payload
24599     0x11/imm32/alloc-id:fake
24600     _string-break-if-float<=/imm32/name
24601     0x11/imm32/alloc-id:fake
24602     Single-lit-var/imm32/inouts
24603     0/imm32/no-outputs
24604     0/imm32/no-outputs
24605     0x11/imm32/alloc-id:fake
24606     _string_0f_86_jump_label/imm32/subx-name
24607     0/imm32/no-rm32
24608     0/imm32/no-r32
24609     0/imm32/no-imm32
24610     0/imm32/no-imm8
24611     1/imm32/disp32-is-first-inout
24612     0/imm32/no-xm32
24613     0/imm32/no-x32
24614     0x11/imm32/alloc-id:fake
24615     _Primitive-break-if-float>-named/imm32/next
24616 _Primitive-break-if-float>-named:  # (payload primitive)
24617     0x11/imm32/alloc-id:fake:payload
24618     0x11/imm32/alloc-id:fake
24619     _string-break-if-float>/imm32/name
24620     0x11/imm32/alloc-id:fake
24621     Single-lit-var/imm32/inouts
24622     0/imm32/no-outputs
24623     0/imm32/no-outputs
24624     0x11/imm32/alloc-id:fake
24625     _string_0f_87_jump_label/imm32/subx-name
24626     0/imm32/no-rm32
24627     0/imm32/no-r32
24628     0/imm32/no-imm32
24629     0/imm32/no-imm8
24630     1/imm32/disp32-is-first-inout
24631     0/imm32/no-xm32
24632     0/imm32/no-x32
24633     0x11/imm32/alloc-id:fake
24634     _Primitive-loop-if-float<-named/imm32/next
24635 _Primitive-loop-if-float<-named:  # (payload primitive)
24636     0x11/imm32/alloc-id:fake:payload
24637     0x11/imm32/alloc-id:fake
24638     _string-loop-if-float</imm32/name
24639     0x11/imm32/alloc-id:fake
24640     Single-lit-var/imm32/inouts
24641     0/imm32/no-outputs
24642     0/imm32/no-outputs
24643     0x11/imm32/alloc-id:fake
24644     _string_0f_82_jump_label/imm32/subx-name
24645     0/imm32/no-rm32
24646     0/imm32/no-r32
24647     0/imm32/no-imm32
24648     0/imm32/no-imm8
24649     1/imm32/disp32-is-first-inout
24650     0/imm32/no-xm32
24651     0/imm32/no-x32
24652     0x11/imm32/alloc-id:fake
24653     _Primitive-loop-if-float>=-named/imm32/next
24654 _Primitive-loop-if-float>=-named:  # (payload primitive)
24655     0x11/imm32/alloc-id:fake:payload
24656     0x11/imm32/alloc-id:fake
24657     _string-loop-if-float>=/imm32/name
24658     0x11/imm32/alloc-id:fake
24659     Single-lit-var/imm32/inouts
24660     0/imm32/no-outputs
24661     0/imm32/no-outputs
24662     0x11/imm32/alloc-id:fake
24663     _string_0f_83_jump_label/imm32/subx-name
24664     0/imm32/no-rm32
24665     0/imm32/no-r32
24666     0/imm32/no-imm32
24667     0/imm32/no-imm8
24668     1/imm32/disp32-is-first-inout
24669     0/imm32/no-xm32
24670     0/imm32/no-x32
24671     0x11/imm32/alloc-id:fake
24672     _Primitive-loop-if-float<=-named/imm32/next
24673 _Primitive-loop-if-float<=-named:  # (payload primitive)
24674     0x11/imm32/alloc-id:fake:payload
24675     0x11/imm32/alloc-id:fake
24676     _string-loop-if-float<=/imm32/name
24677     0x11/imm32/alloc-id:fake
24678     Single-lit-var/imm32/inouts
24679     0/imm32/no-outputs
24680     0/imm32/no-outputs
24681     0x11/imm32/alloc-id:fake
24682     _string_0f_86_jump_label/imm32/subx-name
24683     0/imm32/no-rm32
24684     0/imm32/no-r32
24685     0/imm32/no-imm32
24686     0/imm32/no-imm8
24687     1/imm32/disp32-is-first-inout
24688     0/imm32/no-xm32
24689     0/imm32/no-x32
24690     0x11/imm32/alloc-id:fake
24691     _Primitive-loop-if-float>-named/imm32/next
24692 _Primitive-loop-if-float>-named:  # (payload primitive)
24693     0x11/imm32/alloc-id:fake:payload
24694     0x11/imm32/alloc-id:fake
24695     _string-loop-if-float>/imm32/name
24696     0x11/imm32/alloc-id:fake
24697     Single-lit-var/imm32/inouts
24698     0/imm32/no-outputs
24699     0/imm32/no-outputs
24700     0x11/imm32/alloc-id:fake
24701     _string_0f_87_jump_label/imm32/subx-name
24702     0/imm32/no-rm32
24703     0/imm32/no-r32
24704     0/imm32/no-imm32
24705     0/imm32/no-imm8
24706     1/imm32/disp32-is-first-inout
24707     0/imm32/no-xm32
24708     0/imm32/no-x32
24709     0/imm32/next
24710     0/imm32/next
24711 
24712 # string literals for Mu instructions
24713 _string-add:  # (payload array byte)
24714     0x11/imm32/alloc-id:fake:payload
24715     # "add"
24716     0x3/imm32/size
24717     0x61/a 0x64/d 0x64/d
24718 _string-address:  # (payload array byte)
24719     0x11/imm32/alloc-id:fake:payload
24720     # "address"
24721     0x7/imm32/size
24722     0x61/a 0x64/d 0x64/d 0x72/r 0x65/e 0x73/s 0x73/s
24723 _string-add-to:  # (payload array byte)
24724     0x11/imm32/alloc-id:fake:payload
24725     # "add-to"
24726     0x6/imm32/size
24727     0x61/a 0x64/d 0x64/d 0x2d/dash 0x74/t 0x6f/o
24728 _string-and:  # (payload array byte)
24729     0x11/imm32/alloc-id:fake:payload
24730     # "and"
24731     0x3/imm32/size
24732     0x61/a 0x6e/n 0x64/d
24733 _string-and-with:  # (payload array byte)
24734     0x11/imm32/alloc-id:fake:payload
24735     # "and-with"
24736     0x8/imm32/size
24737     0x61/a 0x6e/n 0x64/d 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
24738 _string-break:  # (payload array byte)
24739     0x11/imm32/alloc-id:fake:payload
24740     # "break"
24741     0x5/imm32/size
24742     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k
24743 _string-break-if-<:  # (payload array byte)
24744     0x11/imm32/alloc-id:fake:payload
24745     # "break-if-<"
24746     0xa/imm32/size
24747     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/<
24748 _string-break-if-<=:  # (payload array byte)
24749     0x11/imm32/alloc-id:fake:payload
24750     # "break-if-<="
24751     0xb/imm32/size
24752     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< 0x3d/=
24753 _string-break-if-=:  # (payload array byte)
24754     0x11/imm32/alloc-id:fake:payload
24755     # "break-if-="
24756     0xa/imm32/size
24757     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3d/=
24758 _string-break-if->:  # (payload array byte)
24759     0x11/imm32/alloc-id:fake:payload
24760     # "break-if->"
24761     0xa/imm32/size
24762     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/>
24763 _string-break-if->=:  # (payload array byte)
24764     0x11/imm32/alloc-id:fake:payload
24765     # "break-if->="
24766     0xb/imm32/size
24767     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> 0x3d/=
24768 _string-break-if-!=:  # (payload array byte)
24769     0x11/imm32/alloc-id:fake:payload
24770     # "break-if-!="
24771     0xb/imm32/size
24772     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x21/! 0x3d/=
24773 _string-break-if-addr<:  # (payload array byte)
24774     0x11/imm32/alloc-id:fake:payload
24775     # "break-if-addr<"
24776     0xe/imm32/size
24777     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/<
24778 _string-break-if-addr<=:  # (payload array byte)
24779     0x11/imm32/alloc-id:fake:payload
24780     # "break-if-addr<="
24781     0xf/imm32/size
24782     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/=
24783 _string-break-if-addr>:  # (payload array byte)
24784     0x11/imm32/alloc-id:fake:payload
24785     # "break-if-addr>"
24786     0xe/imm32/size
24787     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/>
24788 _string-break-if-addr>=:  # (payload array byte)
24789     0x11/imm32/alloc-id:fake:payload
24790     # "break-if-addr>="
24791     0xf/imm32/size
24792     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/=
24793 _string-break-if-float<:  # (payload array byte)
24794     0x11/imm32/alloc-id:fake:payload
24795     # "break-if-float<"
24796     0xf/imm32/size
24797     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/<
24798 _string-break-if-float<=:  # (payload array byte)
24799     0x11/imm32/alloc-id:fake:payload
24800     # "break-if-float<="
24801     0x10/imm32/size
24802     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/=
24803 _string-break-if-float>:  # (payload array byte)
24804     0x11/imm32/alloc-id:fake:payload
24805     # "break-if-float>"
24806     0xf/imm32/size
24807     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/>
24808 _string-break-if-float>=:  # (payload array byte)
24809     0x11/imm32/alloc-id:fake:payload
24810     # "break-if-float>="
24811     0x10/imm32/size
24812     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/=
24813 _string-compare:  # (payload array byte)
24814     0x11/imm32/alloc-id:fake:payload
24815     # "compare"
24816     0x7/imm32/size
24817     0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e
24818 _string-copy:  # (payload array byte)
24819     0x11/imm32/alloc-id:fake:payload
24820     # "copy"
24821     0x4/imm32/size
24822     0x63/c 0x6f/o 0x70/p 0x79/y
24823 _string-copy-to:  # (payload array byte)
24824     0x11/imm32/alloc-id:fake:payload
24825     # "copy-to"
24826     0x7/imm32/size
24827     0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/dash 0x74/t 0x6f/o
24828 _string-copy-byte:
24829     0x11/imm32/alloc-id:fake:payload
24830     # "copy-byte"
24831     0x9/imm32/size
24832     0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/- 0x62/b 0x79/y 0x74/t 0x65/e
24833 _string-copy-byte-to:
24834     0x11/imm32/alloc-id:fake:payload
24835     # "copy-byte-to"
24836     0xc/imm32/size
24837     0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/- 0x62/b 0x79/y 0x74/t 0x65/e 0x2d/- 0x74/t 0x6f/o
24838 _string-decrement:  # (payload array byte)
24839     0x11/imm32/alloc-id:fake:payload
24840     # "decrement"
24841     0x9/imm32/size
24842     0x64/d 0x65/e 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t
24843 _string-increment:  # (payload array byte)
24844     0x11/imm32/alloc-id:fake:payload
24845     # "increment"
24846     0x9/imm32/size
24847     0x69/i 0x6e/n 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t
24848 _string-loop:  # (payload array byte)
24849     0x11/imm32/alloc-id:fake:payload
24850     # "loop"
24851     0x4/imm32/size
24852     0x6c/l 0x6f/o 0x6f/o 0x70/p
24853 _string-loop-if-<:  # (payload array byte)
24854     0x11/imm32/alloc-id:fake:payload
24855     # "loop-if-<"
24856     0x9/imm32/size
24857     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/<
24858 _string-loop-if-<=:  # (payload array byte)
24859     0x11/imm32/alloc-id:fake:payload
24860     # "loop-if-<="
24861     0xa/imm32/size
24862     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< 0x3d/=
24863 _string-loop-if-=:  # (payload array byte)
24864     0x11/imm32/alloc-id:fake:payload
24865     # "loop-if-="
24866     0x9/imm32/size
24867     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3d/=
24868 _string-loop-if->:  # (payload array byte)
24869     0x11/imm32/alloc-id:fake:payload
24870     # "loop-if->"
24871     0x9/imm32/size
24872     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/>
24873 _string-loop-if->=:  # (payload array byte)
24874     0x11/imm32/alloc-id:fake:payload
24875     # "loop-if->="
24876     0xa/imm32/size
24877     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> 0x3d/=
24878 _string-loop-if-!=:  # (payload array byte)
24879     0x11/imm32/alloc-id:fake:payload
24880     # "loop-if-!="
24881     0xa/imm32/size
24882     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x21/! 0x3d/=
24883 _string-loop-if-addr<:  # (payload array byte)
24884     0x11/imm32/alloc-id:fake:payload
24885     # "loop-if-addr<"
24886     0xd/imm32/size
24887     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/<
24888 _string-loop-if-addr<=:  # (payload array byte)
24889     0x11/imm32/alloc-id:fake:payload
24890     # "loop-if-addr<="
24891     0xe/imm32/size
24892     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/=
24893 _string-loop-if-addr>:  # (payload array byte)
24894     0x11/imm32/alloc-id:fake:payload
24895     # "loop-if-addr>"
24896     0xd/imm32/size
24897     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/>
24898 _string-loop-if-addr>=:  # (payload array byte)
24899     0x11/imm32/alloc-id:fake:payload
24900     # "loop-if-addr>="
24901     0xe/imm32/size
24902     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/=
24903 _string-loop-if-float<:  # (payload array byte)
24904     0x11/imm32/alloc-id:fake:payload
24905     # "loop-if-float<"
24906     0xe/imm32/size
24907     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/<
24908 _string-loop-if-float<=:  # (payload array byte)
24909     0x11/imm32/alloc-id:fake:payload
24910     # "loop-if-float<="
24911     0xf/imm32/size
24912     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/=
24913 _string-loop-if-float>:  # (payload array byte)
24914     0x11/imm32/alloc-id:fake:payload
24915     # "loop-if-float>"
24916     0xe/imm32/size
24917     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/>
24918 _string-loop-if-float>=:  # (payload array byte)
24919     0x11/imm32/alloc-id:fake:payload
24920     # "loop-if-float>="
24921     0xf/imm32/size
24922     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/=
24923 _string-multiply:  # (payload array byte)
24924     0x11/imm32/alloc-id:fake:payload
24925     # "multiply"
24926     0x8/imm32/size
24927     0x6d/m 0x75/u 0x6c/l 0x74/t 0x69/i 0x70/p 0x6c/l 0x79/y
24928 _string-convert:  # (payload array byte)
24929     0x11/imm32/alloc-id:fake:payload
24930     # "convert"
24931     0x7/imm32/size
24932     0x63/c 0x6f/o 0x6e/n 0x76/v 0x65/e 0x72/r 0x74/t
24933 _string-truncate:  # (payload array byte)
24934     0x11/imm32/alloc-id:fake:payload
24935     # "truncate"
24936     0x8/imm32/size
24937     0x74/t 0x72/r 0x75/u 0x6e/n 0x63/c 0x61/a 0x74/t 0x65/e
24938 _string-reinterpret:  # (payload array byte)
24939     0x11/imm32/alloc-id:fake:payload
24940     # "reinterpret"
24941     0xb/imm32/size
24942     0x72/r 0x65/e 0x69/i 0x6e/n 0x74/t 0x65/e 0x72/r 0x70/p 0x72/r 0x65/e 0x74/t
24943 _string-divide:
24944     0x11/imm32/alloc-id:fake:payload
24945     # "divide"
24946     0x6/imm32/size
24947     0x64/d 0x69/i 0x76/v 0x69/i 0x64/d 0x65/e
24948 _string-max:
24949     0x11/imm32/alloc-id:fake:payload
24950     # "max"
24951     0x3/imm32/size
24952     0x6d/m 0x61/a 0x78/x
24953 _string-min:
24954     0x11/imm32/alloc-id:fake:payload
24955     # "min"
24956     0x3/imm32/size
24957     0x6d/m 0x69/i 0x6e/n
24958 _string-reciprocal:
24959     0x11/imm32/alloc-id:fake:payload
24960     # "reciprocal"
24961     0xa/imm32/size
24962     0x72/r 0x65/e 0x63/c 0x69/i 0x70/p 0x72/r 0x6f/o 0x63/c 0x61/a 0x6c/l
24963 _string-square-root:
24964     0x11/imm32/alloc-id:fake:payload
24965     # "square-root"
24966     0xb/imm32/size
24967     0x73/s 0x71/q 0x75/u 0x61/a 0x72/r 0x65/e 0x2d/- 0x72/r 0x6f/o 0x6f/o 0x74/t
24968 _string-inverse-square-root:
24969     0x11/imm32/alloc-id:fake:payload
24970     # "inverse-square-root"
24971     0x13/imm32/size
24972     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
24973 _string-negate:  # (payload array byte)
24974     0x11/imm32/alloc-id:fake:payload
24975     # "negate"
24976     0x6/imm32/size
24977     0x6e/n 0x65/e 0x67/g 0x61/a 0x74/t 0x65/e
24978 _string-or:  # (payload array byte)
24979     0x11/imm32/alloc-id:fake:payload
24980     # "or"
24981     0x2/imm32/size
24982     0x6f/o 0x72/r
24983 _string-or-with:  # (payload array byte)
24984     0x11/imm32/alloc-id:fake:payload
24985     # "or-with"
24986     0x7/imm32/size
24987     0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
24988 _string-subtract:  # (payload array byte)
24989     0x11/imm32/alloc-id:fake:payload
24990     # "subtract"
24991     0x8/imm32/size
24992     0x73/s 0x75/u 0x62/b 0x74/t 0x72/r 0x61/a 0x63/c 0x74/t
24993 _string-subtract-from:  # (payload array byte)
24994     0x11/imm32/alloc-id:fake:payload
24995     # "subtract-from"
24996     0xd/imm32/size
24997     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
24998 _string-xor:  # (payload array byte)
24999     0x11/imm32/alloc-id:fake:payload
25000     # "xor"
25001     0x3/imm32/size
25002     0x78/x 0x6f/o 0x72/r
25003 _string-xor-with:  # (payload array byte)
25004     0x11/imm32/alloc-id:fake:payload
25005     # "xor-with"
25006     0x8/imm32/size
25007     0x78/x 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
25008 _string-shift-left:  # (payload array byte)
25009     0x11/imm32/alloc-id:fake:payload
25010     # "shift-left"
25011     0xa/imm32/size
25012     0x73/s 0x68/h 0x69/i 0x66/f 0x74/t 0x2d/dash 0x6c/l 0x65/e 0x66/f 0x74/t
25013 _string-shift-right:  # (payload array byte)
25014     0x11/imm32/alloc-id:fake:payload
25015     # "shift-right"
25016     0xb/imm32/size
25017     0x73/s 0x68/h 0x69/i 0x66/f 0x74/t 0x2d/dash 0x72/r 0x69/i 0x67/g 0x68/h 0x74/t
25018 _string-shift-right-signed:  # (payload array byte)
25019     0x11/imm32/alloc-id:fake:payload
25020     # "shift-right-signed"
25021     0x12/imm32/size
25022     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
25023 
25024 # string literals for SubX instructions
25025 _string_01_add_to:  # (payload array byte)
25026     0x11/imm32/alloc-id:fake:payload
25027     # "01/add-to"
25028     0x9/imm32/size
25029     0x30/0 0x31/1 0x2f/slash 0x61/a 0x64/d 0x64/d 0x2d/dash 0x74/t 0x6f/o
25030 _string_03_add:  # (payload array byte)
25031     0x11/imm32/alloc-id:fake:payload
25032     # "03/add"
25033     0x6/imm32/size
25034     0x30/0 0x33/3 0x2f/slash 0x61/a 0x64/d 0x64/d
25035 _string_05_add_to_eax:  # (payload array byte)
25036     0x11/imm32/alloc-id:fake:payload
25037     # "05/add-to-eax"
25038     0xd/imm32/size
25039     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
25040 _string_09_or_with:  # (payload array byte)
25041     0x11/imm32/alloc-id:fake:payload
25042     # "09/or-with"
25043     0xa/imm32/size
25044     0x30/0 0x39/9 0x2f/slash 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
25045 _string_0b_or:  # (payload array byte)
25046     0x11/imm32/alloc-id:fake:payload
25047     # "0b/or"
25048     0x5/imm32/size
25049     0x30/0 0x62/b 0x2f/slash 0x6f/o 0x72/r
25050 _string_0d_or_with_eax:  # (payload array byte)
25051     0x11/imm32/alloc-id:fake:payload
25052     # "0d/or-with-eax"
25053     0xe/imm32/size
25054     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
25055 _string_0f_82_jump_label:  # (payload array byte)
25056     0x11/imm32/alloc-id:fake:payload
25057     # "0f 82/jump-if-addr<"
25058     0x13/imm32/size
25059     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/<
25060 _string_0f_82_jump_break:  # (payload array byte)
25061     0x11/imm32/alloc-id:fake:payload
25062     # "0f 82/jump-if-addr< break/disp32"
25063     0x20/imm32/size
25064     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
25065 _string_0f_82_jump_loop:  # (payload array byte)
25066     0x11/imm32/alloc-id:fake:payload
25067     # "0f 82/jump-if-addr< loop/disp32"
25068     0x1f/imm32/size
25069     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
25070 _string_0f_83_jump_label:  # (payload array byte)
25071     0x11/imm32/alloc-id:fake:payload
25072     # "0f 83/jump-if-addr>="
25073     0x14/imm32/size
25074     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/=
25075 _string_0f_83_jump_break:  # (payload array byte)
25076     0x11/imm32/alloc-id:fake:payload
25077     # "0f 83/jump-if-addr>= break/disp32"
25078     0x21/imm32/size
25079     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
25080 _string_0f_83_jump_loop:  # (payload array byte)
25081     0x11/imm32/alloc-id:fake:payload
25082     # "0f 83/jump-if-addr>= loop/disp32"
25083     0x20/imm32/size
25084     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
25085 _string_0f_84_jump_label:  # (payload array byte)
25086     0x11/imm32/alloc-id:fake:payload
25087     # "0f 84/jump-if-="
25088     0xf/imm32/size
25089     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/=
25090 _string_0f_84_jump_break:  # (payload array byte)
25091     0x11/imm32/alloc-id:fake:payload
25092     # "0f 84/jump-if-= break/disp32"
25093     0x1c/imm32/size
25094     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
25095 _string_0f_84_jump_loop:  # (payload array byte)
25096     0x11/imm32/alloc-id:fake:payload
25097     # "0f 84/jump-if-= loop/disp32"
25098     0x1b/imm32/size
25099     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
25100 _string_0f_85_jump_label:  # (payload array byte)
25101     0x11/imm32/alloc-id:fake:payload
25102     # "0f 85/jump-if-!="
25103     0x10/imm32/size
25104     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/=
25105 _string_0f_85_jump_break:  # (payload array byte)
25106     0x11/imm32/alloc-id:fake:payload
25107     # "0f 85/jump-if-!= break/disp32"
25108     0x1d/imm32/size
25109     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
25110 _string_0f_85_jump_loop:  # (payload array byte)
25111     0x11/imm32/alloc-id:fake:payload
25112     # "0f 85/jump-if-!= loop/disp32"
25113     0x1c/imm32/size
25114     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
25115 _string_0f_86_jump_label:  # (payload array byte)
25116     0x11/imm32/alloc-id:fake:payload
25117     # "0f 86/jump-if-addr<="
25118     0x14/imm32/size
25119     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/=
25120 _string_0f_86_jump_break:  # (payload array byte)
25121     0x11/imm32/alloc-id:fake:payload
25122     # "0f 86/jump-if-addr<= break/disp32"
25123     0x21/imm32/size
25124     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
25125 _string_0f_86_jump_loop:  # (payload array byte)
25126     0x11/imm32/alloc-id:fake:payload
25127     # "0f 86/jump-if-addr<= loop/disp32"
25128     0x20/imm32/size
25129     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
25130 _string_0f_87_jump_label:  # (payload array byte)
25131     0x11/imm32/alloc-id:fake:payload
25132     # "0f 87/jump-if-addr>"
25133     0x13/imm32/size
25134     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/>
25135 _string_0f_87_jump_break:  # (payload array byte)
25136     0x11/imm32/alloc-id:fake:payload
25137     # "0f 87/jump-if-addr> break/disp32"
25138     0x20/imm32/size
25139     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
25140 _string_0f_87_jump_loop:  # (payload array byte)
25141     0x11/imm32/alloc-id:fake:payload
25142     # "0f 87/jump-if-addr> loop/disp32"
25143     0x1f/imm32/size
25144     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
25145 _string_0f_8c_jump_label:  # (payload array byte)
25146     0x11/imm32/alloc-id:fake:payload
25147     # "0f 8c/jump-if-<"
25148     0xf/imm32/size
25149     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/<
25150 _string_0f_8c_jump_break:  # (payload array byte)
25151     0x11/imm32/alloc-id:fake:payload
25152     # "0f 8c/jump-if-< break/disp32"
25153     0x1c/imm32/size
25154     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
25155 _string_0f_8c_jump_loop:  # (payload array byte)
25156     0x11/imm32/alloc-id:fake:payload
25157     # "0f 8c/jump-if-< loop/disp32"
25158     0x1b/imm32/size
25159     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
25160 _string_0f_8d_jump_label:  # (payload array byte)
25161     0x11/imm32/alloc-id:fake:payload
25162     # "0f 8d/jump-if->="
25163     0x10/imm32/size
25164     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/=
25165 _string_0f_8d_jump_break:  # (payload array byte)
25166     0x11/imm32/alloc-id:fake:payload
25167     # "0f 8d/jump-if->= break/disp32"
25168     0x1d/imm32/size
25169     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
25170 _string_0f_8d_jump_loop:  # (payload array byte)
25171     0x11/imm32/alloc-id:fake:payload
25172     # "0f 8d/jump-if->= loop/disp32"
25173     0x1c/imm32/size
25174     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
25175 _string_0f_8e_jump_label:  # (payload array byte)
25176     0x11/imm32/alloc-id:fake:payload
25177     # "0f 8e/jump-if-<="
25178     0x10/imm32/size
25179     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/=
25180 _string_0f_8e_jump_break:  # (payload array byte)
25181     0x11/imm32/alloc-id:fake:payload
25182     # "0f 8e/jump-if-<= break/disp32"
25183     0x1d/imm32/size
25184     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
25185 _string_0f_8e_jump_loop:  # (payload array byte)
25186     0x11/imm32/alloc-id:fake:payload
25187     # "0f 8e/jump-if-<= loop/disp32"
25188     0x1c/imm32/size
25189     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
25190 _string_0f_8f_jump_label:  # (payload array byte)
25191     0x11/imm32/alloc-id:fake:payload
25192     # "0f 8f/jump-if->"
25193     0xf/imm32/size
25194     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/>
25195 _string_0f_8f_jump_break:  # (payload array byte)
25196     0x11/imm32/alloc-id:fake:payload
25197     # "0f 8f/jump-if-> break/disp32"
25198     0x1c/imm32/size
25199     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
25200 _string_0f_8f_jump_loop:  # (payload array byte)
25201     0x11/imm32/alloc-id:fake:payload
25202     # "0f 8f/jump-if-> loop/disp32"
25203     0x1b/imm32/size
25204     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
25205 _string_0f_af_multiply:  # (payload array byte)
25206     0x11/imm32/alloc-id:fake:payload
25207     # "0f af/multiply"
25208     0xe/imm32/size
25209     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
25210 _string_f3_0f_2a_convert_to_float:
25211     0x11/imm32/alloc-id:fake:payload
25212     # "f3 0f 2a/convert-to-float"
25213     0x19/imm32/size
25214     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
25215 _string_f3_0f_2d_convert_to_int:
25216     0x11/imm32/alloc-id:fake:payload
25217     # "f3 0f 2d/convert-to-int"
25218     0x17/imm32/size
25219     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
25220 _string_f3_0f_2c_truncate_to_int:
25221     0x11/imm32/alloc-id:fake:payload
25222     # "f3 0f 2c/truncate-to-int"
25223     0x18/imm32/size
25224     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
25225 _string_f3_0f_58_add:
25226     0x11/imm32/alloc-id:fake:payload
25227     # "f3 0f 58/add"
25228     0xc/imm32/size
25229     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x38/8 0x2f/slash 0x61/a 0x64/d 0x64/d
25230 _string_f3_0f_5c_subtract:
25231     0x11/imm32/alloc-id:fake:payload
25232     # "f3 0f 5c/subtract"
25233     0x11/imm32/size
25234     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
25235 _string_f3_0f_59_multiply:
25236     0x11/imm32/alloc-id:fake:payload
25237     # "f3 0f 59/multiply"
25238     0x11/imm32/size
25239     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
25240 _string_f3_0f_5e_divide:
25241     0x11/imm32/alloc-id:fake:payload
25242     # "f3 0f 5e/divide"
25243     0xf/imm32/size
25244     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
25245 _string_f3_0f_53_reciprocal:
25246     0x11/imm32/alloc-id:fake:payload
25247     # "f3 0f 53/reciprocal"
25248     0x13/imm32/size
25249     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
25250 _string_f3_0f_51_square_root:
25251     0x11/imm32/alloc-id:fake:payload
25252     # "f3 0f 51/square-root"
25253     0x14/imm32/size
25254     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
25255 _string_f3_0f_52_inverse_square_root:
25256     0x11/imm32/alloc-id:fake:payload
25257     # "f3 0f 52/inverse-square-root"
25258     0x1c/imm32/size
25259     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
25260 _string_f3_0f_5d_min:
25261     0x11/imm32/alloc-id:fake:payload
25262     # "f3 0f 5d/min"
25263     0xc/imm32/size
25264     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x64/d 0x2f/slash 0x6d/m 0x69/i 0x6e/n
25265 _string_f3_0f_5f_max:
25266     0x11/imm32/alloc-id:fake:payload
25267     # "f3 0f 5f/max"
25268     0xc/imm32/size
25269     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x66/f 0x2f/slash 0x6d/m 0x61/a 0x78/x
25270 _string_f3_0f_10_copy:
25271     0x11/imm32/alloc-id:fake:payload
25272     # "f3 0f 10/copy"
25273     0xd/imm32/size
25274     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
25275 _string_f3_0f_11_copy:
25276     0x11/imm32/alloc-id:fake:payload
25277     # "f3 0f 11/copy"
25278     0xd/imm32/size
25279     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
25280 _string_0f_2f_compare:
25281     0x11/imm32/alloc-id:fake:payload
25282     # "0f 2f/compare"
25283     0xd/imm32/size
25284     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
25285 _string_21_and_with:  # (payload array byte)
25286     0x11/imm32/alloc-id:fake:payload
25287     # "21/and-with"
25288     0xb/imm32/size
25289     0x32/2 0x31/1 0x2f/slash 0x61/a 0x6e/n 0x64/d 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
25290 _string_23_and:  # (payload array byte)
25291     0x11/imm32/alloc-id:fake:payload
25292     # "23/and"
25293     0x6/imm32/size
25294     0x32/2 0x33/3 0x2f/slash 0x61/a 0x6e/n 0x64/d
25295 _string_25_and_with_eax:  # (payload array byte)
25296     0x11/imm32/alloc-id:fake:payload
25297     # "25/and-with-eax"
25298     0xf/imm32/size
25299     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
25300 _string_29_subtract_from:  # (payload array byte)
25301     0x11/imm32/alloc-id:fake:payload
25302     # "29/subtract-from"
25303     0x10/imm32/size
25304     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
25305 _string_2b_subtract:  # (payload array byte)
25306     0x11/imm32/alloc-id:fake:payload
25307     # "2b/subtract"
25308     0xb/imm32/size
25309     0x32/2 0x62/b 0x2f/slash 0x73/s 0x75/u 0x62/b 0x74/t 0x72/r 0x61/a 0x63/c 0x74/t
25310 _string_2d_subtract_from_eax:  # (payload array byte)
25311     0x11/imm32/alloc-id:fake:payload
25312     # "2d/subtract-from-eax"
25313     0x14/imm32/size
25314     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
25315 _string_31_xor_with:  # (payload array byte)
25316     0x11/imm32/alloc-id:fake:payload
25317     # "31/xor-with"
25318     0xb/imm32/size
25319     0x33/3 0x31/1 0x2f/slash 0x78/x 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
25320 _string_33_xor:  # (payload array byte)
25321     0x11/imm32/alloc-id:fake:payload
25322     # "33/xor"
25323     0x6/imm32/size
25324     0x33/3 0x33/3 0x2f/slash 0x78/x 0x6f/o 0x72/r
25325 _string_35_xor_with_eax:  # (payload array byte)
25326     0x11/imm32/alloc-id:fake:payload
25327     # "35/xor-with-eax"
25328     0xf/imm32/size
25329     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
25330 _string_39_compare->:  # (payload array byte)
25331     0x11/imm32/alloc-id:fake:payload
25332     # "39/compare->"
25333     0xc/imm32/size
25334     0x33/3 0x39/9 0x2f/slash 0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e 0x2d/dash 0x3e/>
25335 _string_3b_compare<-:  # (payload array byte)
25336     0x11/imm32/alloc-id:fake:payload
25337     # "3b/compare<-"
25338     0xc/imm32/size
25339     0x33/3 0x62/b 0x2f/slash 0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e 0x3c/< 0x2d/dash
25340 _string_3d_compare_eax_with:  # (payload array byte)
25341     0x11/imm32/alloc-id:fake:payload
25342     # "3d/compare-eax-with"
25343     0x13/imm32/size
25344     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
25345 _string_40_increment_eax:  # (payload array byte)
25346     0x11/imm32/alloc-id:fake:payload
25347     # "40/increment-eax"
25348     0x10/imm32/size
25349     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
25350 _string_41_increment_ecx:  # (payload array byte)
25351     0x11/imm32/alloc-id:fake:payload
25352     # "41/increment-ecx"
25353     0x10/imm32/size
25354     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
25355 _string_42_increment_edx:  # (payload array byte)
25356     0x11/imm32/alloc-id:fake:payload
25357     # "42/increment-edx"
25358     0x10/imm32/size
25359     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
25360 _string_43_increment_ebx:  # (payload array byte)
25361     0x11/imm32/alloc-id:fake:payload
25362     # "43/increment-ebx"
25363     0x10/imm32/size
25364     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
25365 _string_46_increment_esi:  # (payload array byte)
25366     0x11/imm32/alloc-id:fake:payload
25367     # "46/increment-esi"
25368     0x10/imm32/size
25369     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
25370 _string_47_increment_edi:  # (payload array byte)
25371     0x11/imm32/alloc-id:fake:payload
25372     # "47/increment-edi"
25373     0x10/imm32/size
25374     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
25375 _string_48_decrement_eax:  # (payload array byte)
25376     0x11/imm32/alloc-id:fake:payload
25377     # "48/decrement-eax"
25378     0x10/imm32/size
25379     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
25380 _string_49_decrement_ecx:  # (payload array byte)
25381     0x11/imm32/alloc-id:fake:payload
25382     # "49/decrement-ecx"
25383     0x10/imm32/size
25384     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
25385 _string_4a_decrement_edx:  # (payload array byte)
25386     0x11/imm32/alloc-id:fake:payload
25387     # "4a/decrement-edx"
25388     0x10/imm32/size
25389     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
25390 _string_4b_decrement_ebx:  # (payload array byte)
25391     0x11/imm32/alloc-id:fake:payload
25392     # "4b/decrement-ebx"
25393     0x10/imm32/size
25394     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
25395 _string_4e_decrement_esi:  # (payload array byte)
25396     0x11/imm32/alloc-id:fake:payload
25397     # "4e/decrement-esi"
25398     0x10/imm32/size
25399     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
25400 _string_4f_decrement_edi:  # (payload array byte)
25401     0x11/imm32/alloc-id:fake:payload
25402     # "4f/decrement-edi"
25403     0x10/imm32/size
25404     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
25405 _string_81_subop_add:  # (payload array byte)
25406     0x11/imm32/alloc-id:fake:payload
25407     # "81 0/subop/add"
25408     0xe/imm32/size
25409     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
25410 _string_81_subop_or:  # (payload array byte)
25411     0x11/imm32/alloc-id:fake:payload
25412     # "81 1/subop/or"
25413     0xd/imm32/size
25414     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
25415 _string_81_subop_and:  # (payload array byte)
25416     0x11/imm32/alloc-id:fake:payload
25417     # "81 4/subop/and"
25418     0xe/imm32/size
25419     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
25420 _string_81_subop_subtract:  # (payload array byte)
25421     0x11/imm32/alloc-id:fake:payload
25422     # "81 5/subop/subtract"
25423     0x13/imm32/size
25424     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
25425 _string_81_subop_xor:  # (payload array byte)
25426     0x11/imm32/alloc-id:fake:payload
25427     # "81 6/subop/xor"
25428     0xe/imm32/size
25429     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
25430 _string_81_subop_compare:  # (payload array byte)
25431     0x11/imm32/alloc-id:fake:payload
25432     # "81 7/subop/compare"
25433     0x12/imm32/size
25434     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
25435 _string_89_<-:  # (payload array byte)
25436     0x11/imm32/alloc-id:fake:payload
25437     # "89/<-"
25438     0x5/imm32/size
25439     0x38/8 0x39/9 0x2f/slash 0x3c/< 0x2d/dash
25440 _string_8b_->:  # (payload array byte)
25441     0x11/imm32/alloc-id:fake:payload
25442     # "8b/->"
25443     0x5/imm32/size
25444     0x38/8 0x62/b 0x2f/slash 0x2d/dash 0x3e/>
25445 _string_8a_copy_byte:
25446     0x11/imm32/alloc-id:fake:payload
25447     # "8a/byte->"
25448     0x9/imm32/size
25449     0x38/8 0x61/a 0x2f// 0x62/b 0x79/y 0x74/t 0x65/e 0x2d/- 0x3e/>
25450 _string_88_copy_byte:
25451     0x11/imm32/alloc-id:fake:payload
25452     # "88/byte<-"
25453     0x9/imm32/size
25454     0x38/8 0x38/8 0x2f// 0x62/b 0x79/y 0x74/t 0x65/e 0x3c/< 0x2d/-
25455 _string_8d_copy_address:  # (payload array byte)
25456     0x11/imm32/alloc-id:fake:payload
25457     # "8d/copy-address"
25458     0xf/imm32/size
25459     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
25460 _string_b8_copy_to_eax:  # (payload array byte)
25461     0x11/imm32/alloc-id:fake:payload
25462     # "b8/copy-to-eax"
25463     0xe/imm32/size
25464     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
25465 _string_b9_copy_to_ecx:  # (payload array byte)
25466     0x11/imm32/alloc-id:fake:payload
25467     # "b9/copy-to-ecx"
25468     0xe/imm32/size
25469     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
25470 _string_ba_copy_to_edx:  # (payload array byte)
25471     0x11/imm32/alloc-id:fake:payload
25472     # "ba/copy-to-edx"
25473     0xe/imm32/size
25474     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
25475 _string_bb_copy_to_ebx:  # (payload array byte)
25476     0x11/imm32/alloc-id:fake:payload
25477     # "bb/copy-to-ebx"
25478     0xe/imm32/size
25479     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
25480 _string_be_copy_to_esi:  # (payload array byte)
25481     0x11/imm32/alloc-id:fake:payload
25482     # "be/copy-to-esi"
25483     0xe/imm32/size
25484     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
25485 _string_bf_copy_to_edi:  # (payload array byte)
25486     0x11/imm32/alloc-id:fake:payload
25487     # "bf/copy-to-edi"
25488     0xe/imm32/size
25489     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
25490 _string_c7_subop_copy:  # (payload array byte)
25491     0x11/imm32/alloc-id:fake:payload
25492     # "c7 0/subop/copy"
25493     0xf/imm32/size
25494     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
25495 _string_e9_jump_label:  # (payload array byte)
25496     0x11/imm32/alloc-id:fake:payload
25497     # "e9/jump"
25498     0x7/imm32/size
25499     0x65/e 0x39/9 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p
25500 _string_e9_jump_break:  # (payload array byte)
25501     0x11/imm32/alloc-id:fake:payload
25502     # "e9/jump break/disp32"
25503     0x14/imm32/size
25504     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
25505 _string_e9_jump_loop:  # (payload array byte)
25506     0x11/imm32/alloc-id:fake:payload
25507     # "e9/jump loop/disp32"
25508     0x13/imm32/size
25509     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
25510 _string_f7_subop_negate:
25511     0x11/imm32/alloc-id:fake:payload
25512     # "f7 3/subop/negate"
25513     0x11/imm32/size
25514     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
25515 _string_ff_subop_increment:  # (payload array byte)
25516     0x11/imm32/alloc-id:fake:payload
25517     # "ff 0/subop/increment"
25518     0x14/imm32/size
25519     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
25520 _string_ff_subop_decrement:  # (payload array byte)
25521     0x11/imm32/alloc-id:fake:payload
25522     # "ff 1/subop/decrement"
25523     0x14/imm32/size
25524     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
25525 _string_c1_subop_shift_left:  # (payload array byte)
25526     0x11/imm32/alloc-id:fake:payload
25527     # "c1/shift 4/subop/left"
25528     0x15/imm32/size
25529     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
25530 _string_c1_subop_shift_right_padding_zeroes:  # (payload array byte)
25531     0x11/imm32/alloc-id:fake:payload
25532     # "c1/shift 5/subop/right-padding-zeroes"
25533     0x25/imm32/size
25534     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
25535 _string_c1_subop_shift_right_preserving_sign:  # (payload array byte)
25536     0x11/imm32/alloc-id:fake:payload
25537     # "c1/shift 7/subop/right-preserving-sign"
25538     0x26/imm32/size
25539     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
25540 
25541 Single-int-var-in-mem:  # (payload list var)
25542     0x11/imm32/alloc-id:fake:payload
25543     0x11/imm32/alloc-id:fake
25544     Int-var-in-mem/imm32
25545     0/imm32/next
25546     0/imm32/next
25547 
25548 Int-var-in-mem:  # (payload var)
25549     0x11/imm32/alloc-id:fake:payload
25550     0/imm32/name
25551     0/imm32/name
25552     0x11/imm32/alloc-id:fake
25553     Type-int/imm32
25554     1/imm32/some-block-depth
25555     1/imm32/some-stack-offset
25556     0/imm32/no-register
25557     0/imm32/no-register
25558 
25559 # Not really legal, but closest we can currently represent a dereference of an (addr byte)
25560 Single-byte-var-in-mem:  # (payload list var)
25561     0x11/imm32/alloc-id:fake:payload
25562     0x11/imm32/alloc-id:fake
25563     Byte-var-in-mem/imm32
25564     0/imm32/next
25565     0/imm32/next
25566 
25567 # Not really legal, but closest we can currently represent a dereference of an (addr byte)
25568 Byte-var-in-mem:  # (payload var)
25569     0x11/imm32/alloc-id:fake:payload
25570     0/imm32/name
25571     0/imm32/name
25572     0x11/imm32/alloc-id:fake
25573     Type-byte/imm32
25574     1/imm32/some-block-depth
25575     1/imm32/some-stack-offset
25576     0/imm32/no-register
25577     0/imm32/no-register
25578 
25579 Two-args-int-stack-int-reg:  # (payload list var)
25580     0x11/imm32/alloc-id:fake:payload
25581     0x11/imm32/alloc-id:fake
25582     Int-var-in-mem/imm32
25583     0x11/imm32/alloc-id:fake
25584     Single-int-var-in-some-register/imm32/next
25585 
25586 Two-int-args-in-regs:  # (payload list var)
25587     0x11/imm32/alloc-id:fake:payload
25588     0x11/imm32/alloc-id:fake
25589     Int-var-in-some-register/imm32
25590     0x11/imm32/alloc-id:fake
25591     Single-int-var-in-some-register/imm32/next
25592 
25593 # Not really legal, but closest we can currently represent a dereference of an (addr byte)
25594 Two-args-byte-stack-byte-reg:  # (payload list var)
25595     0x11/imm32/alloc-id:fake:payload
25596     0x11/imm32/alloc-id:fake
25597     Byte-var-in-mem/imm32
25598     0x11/imm32/alloc-id:fake
25599     Single-byte-var-in-some-register/imm32/next
25600 
25601 Two-args-int-reg-int-stack:  # (payload list var)
25602     0x11/imm32/alloc-id:fake:payload
25603     0x11/imm32/alloc-id:fake
25604     Int-var-in-some-register/imm32
25605     0x11/imm32/alloc-id:fake
25606     Single-int-var-in-mem/imm32/next
25607 
25608 Two-args-int-eax-int-literal:  # (payload list var)
25609     0x11/imm32/alloc-id:fake:payload
25610     0x11/imm32/alloc-id:fake
25611     Int-var-in-eax/imm32
25612     0x11/imm32/alloc-id:fake
25613     Single-lit-var/imm32/next
25614 
25615 Int-var-and-literal:  # (payload list var)
25616     0x11/imm32/alloc-id:fake:payload
25617     0x11/imm32/alloc-id:fake
25618     Int-var-in-mem/imm32
25619     0x11/imm32/alloc-id:fake
25620     Single-lit-var/imm32/next
25621 
25622 Int-var-in-register-and-literal:  # (payload list var)
25623     0x11/imm32/alloc-id:fake:payload
25624     0x11/imm32/alloc-id:fake
25625     Int-var-in-some-register/imm32
25626     0x11/imm32/alloc-id:fake
25627     Single-lit-var/imm32/next
25628 
25629 Two-float-args-in-regs:  # (payload list var)
25630     0x11/imm32/alloc-id:fake:payload
25631     0x11/imm32/alloc-id:fake
25632     Float-var-in-some-register/imm32
25633     0x11/imm32/alloc-id:fake
25634     Single-float-var-in-some-register/imm32/next
25635 
25636 Two-args-float-reg-float-stack:  # (payload list var)
25637     0x11/imm32/alloc-id:fake:payload
25638     0x11/imm32/alloc-id:fake
25639     Float-var-in-some-register/imm32
25640     0x11/imm32/alloc-id:fake
25641     Single-float-var-in-mem/imm32/next
25642 
25643 Two-args-float-stack-float-reg:  # (payload list var)
25644     0x11/imm32/alloc-id:fake:payload
25645     0x11/imm32/alloc-id:fake
25646     Float-var-in-mem/imm32
25647     0x11/imm32/alloc-id:fake
25648     Single-float-var-in-some-register/imm32/next
25649 
25650 Single-int-var-in-some-register:  # (payload list var)
25651     0x11/imm32/alloc-id:fake:payload
25652     0x11/imm32/alloc-id:fake
25653     Int-var-in-some-register/imm32
25654     0/imm32/next
25655     0/imm32/next
25656 
25657 Single-addr-var-in-some-register:  # (payload list var)
25658     0x11/imm32/alloc-id:fake:payload
25659     0x11/imm32/alloc-id:fake
25660     Addr-var-in-some-register/imm32
25661     0/imm32/next
25662     0/imm32/next
25663 
25664 Single-byte-var-in-some-register:  # (payload list var)
25665     0x11/imm32/alloc-id:fake:payload
25666     0x11/imm32/alloc-id:fake
25667     Byte-var-in-some-register/imm32
25668     0/imm32/next
25669     0/imm32/next
25670 
25671 Int-var-in-some-register:  # (payload var)
25672     0x11/imm32/alloc-id:fake:payload
25673     0/imm32/name
25674     0/imm32/name
25675     0x11/imm32/alloc-id:fake
25676     Type-int/imm32
25677     1/imm32/some-block-depth
25678     0/imm32/no-stack-offset
25679     0x11/imm32/alloc-id:fake
25680     Any-register/imm32
25681 
25682 Any-register:  # (payload array byte)
25683     0x11/imm32/alloc-id:fake:payload
25684     1/imm32/size
25685     # data
25686     2a/asterisk
25687 
25688 Addr-var-in-some-register:  # (payload var)
25689     0x11/imm32/alloc-id:fake:payload
25690     0/imm32/name
25691     0/imm32/name
25692     0x11/imm32/alloc-id:fake
25693     Type-addr/imm32
25694     1/imm32/some-block-depth
25695     0/imm32/no-stack-offset
25696     0x11/imm32/alloc-id:fake
25697     Any-register/imm32
25698 
25699 Byte-var-in-some-register:  # (payload var)
25700     0x11/imm32/alloc-id:fake:payload
25701     0/imm32/name
25702     0/imm32/name
25703     0x11/imm32/alloc-id:fake
25704     Type-byte/imm32
25705     1/imm32/some-block-depth
25706     0/imm32/no-stack-offset
25707     0x11/imm32/alloc-id:fake
25708     Any-register/imm32
25709 
25710 Single-int-var-in-eax:  # (payload list var)
25711     0x11/imm32/alloc-id:fake:payload
25712     0x11/imm32/alloc-id:fake
25713     Int-var-in-eax/imm32
25714     0/imm32/next
25715     0/imm32/next
25716 
25717 Int-var-in-eax:
25718     0x11/imm32/alloc-id:fake:payload
25719     0/imm32/name
25720     0/imm32/name
25721     0x11/imm32/alloc-id:fake
25722     Type-int/imm32
25723     1/imm32/some-block-depth
25724     0/imm32/no-stack-offset
25725     0x11/imm32/alloc-id:fake
25726     $Mu-register-eax/imm32  # can't use Register-eax only to keep our buggy tools/treeshake.cc happy (TODO)
25727 
25728 Single-int-var-in-ecx:  # (payload list var)
25729     0x11/imm32/alloc-id:fake:payload
25730     0x11/imm32/alloc-id:fake
25731     Int-var-in-ecx/imm32
25732     0/imm32/next
25733     0/imm32/next
25734 
25735 Int-var-in-ecx:
25736     0x11/imm32/alloc-id:fake:payload
25737     0/imm32/name
25738     0/imm32/name
25739     0x11/imm32/alloc-id:fake
25740     Type-int/imm32
25741     1/imm32/some-block-depth
25742     0/imm32/no-stack-offset
25743     0x11/imm32/alloc-id:fake
25744     $Register-ecx/imm32/register
25745 
25746 Single-int-var-in-edx:  # (payload list var)
25747     0x11/imm32/alloc-id:fake:payload
25748     0x11/imm32/alloc-id:fake
25749     Int-var-in-edx/imm32
25750     0/imm32/next
25751     0/imm32/next
25752 
25753 Int-var-in-edx:  # (payload list var)
25754     0x11/imm32/alloc-id:fake:payload
25755     0/imm32/name
25756     0/imm32/name
25757     0x11/imm32/alloc-id:fake
25758     Type-int/imm32
25759     1/imm32/some-block-depth
25760     0/imm32/no-stack-offset
25761     0x11/imm32/alloc-id:fake
25762     $Register-edx/imm32/register
25763 
25764 Single-int-var-in-ebx:  # (payload list var)
25765     0x11/imm32/alloc-id:fake:payload
25766     0x11/imm32/alloc-id:fake
25767     Int-var-in-ebx/imm32
25768     0/imm32/next
25769     0/imm32/next
25770 
25771 Int-var-in-ebx:  # (payload list var)
25772     0x11/imm32/alloc-id:fake:payload
25773     0/imm32/name
25774     0/imm32/name
25775     0x11/imm32/alloc-id:fake
25776     Type-int/imm32
25777     1/imm32/some-block-depth
25778     0/imm32/no-stack-offset
25779     0x11/imm32/alloc-id:fake
25780     $Register-ebx/imm32/register
25781 
25782 Single-int-var-in-esi:  # (payload list var)
25783     0x11/imm32/alloc-id:fake:payload
25784     0x11/imm32/alloc-id:fake
25785     Int-var-in-esi/imm32
25786     0/imm32/next
25787     0/imm32/next
25788 
25789 Int-var-in-esi:  # (payload list var)
25790     0x11/imm32/alloc-id:fake:payload
25791     0/imm32/name
25792     0/imm32/name
25793     0x11/imm32/alloc-id:fake
25794     Type-int/imm32
25795     1/imm32/some-block-depth
25796     0/imm32/no-stack-offset
25797     0x11/imm32/alloc-id:fake
25798     $Register-esi/imm32/register
25799 
25800 Single-int-var-in-edi:  # (payload list var)
25801     0x11/imm32/alloc-id:fake:payload
25802     0x11/imm32/alloc-id:fake
25803     Int-var-in-edi/imm32
25804     0/imm32/next
25805     0/imm32/next
25806 
25807 Int-var-in-edi:  # (payload list var)
25808     0x11/imm32/alloc-id:fake:payload
25809     0/imm32/name
25810     0/imm32/name
25811     0x11/imm32/alloc-id:fake
25812     Type-int/imm32
25813     1/imm32/some-block-depth
25814     0/imm32/no-stack-offset
25815     0x11/imm32/alloc-id:fake
25816     $Register-edi/imm32/register
25817 
25818 Single-lit-var:  # (payload list var)
25819     0x11/imm32/alloc-id:fake:payload
25820     0x11/imm32/alloc-id:fake
25821     Lit-var/imm32
25822     0/imm32/next
25823     0/imm32/next
25824 
25825 Lit-var:  # (payload var)
25826     0x11/imm32/alloc-id:fake:payload
25827     0/imm32/name
25828     0/imm32/name
25829     0x11/imm32/alloc-id:fake
25830     Type-literal/imm32
25831     1/imm32/some-block-depth
25832     0/imm32/no-stack-offset
25833     0/imm32/no-register
25834     0/imm32/no-register
25835 
25836 Single-float-var-in-mem:  # (payload list var)
25837     0x11/imm32/alloc-id:fake:payload
25838     0x11/imm32/alloc-id:fake
25839     Float-var-in-mem/imm32
25840     0/imm32/next
25841     0/imm32/next
25842 
25843 Float-var-in-mem:  # (payload var)
25844     0x11/imm32/alloc-id:fake:payload
25845     0/imm32/name
25846     0/imm32/name
25847     0x11/imm32/alloc-id:fake
25848     Type-float/imm32
25849     1/imm32/some-block-depth
25850     1/imm32/some-stack-offset
25851     0/imm32/no-register
25852     0/imm32/no-register
25853 
25854 Single-float-var-in-some-register:  # (payload list var)
25855     0x11/imm32/alloc-id:fake:payload
25856     0x11/imm32/alloc-id:fake
25857     Float-var-in-some-register/imm32
25858     0/imm32/next
25859     0/imm32/next
25860 
25861 Float-var-in-some-register:  # (payload var)
25862     0x11/imm32/alloc-id:fake:payload
25863     0/imm32/name
25864     0/imm32/name
25865     0x11/imm32/alloc-id:fake
25866     Type-float/imm32
25867     1/imm32/some-block-depth
25868     0/imm32/no-stack-offset
25869     0x11/imm32/alloc-id:fake
25870     Any-register/imm32
25871 
25872 Type-int:  # (payload type-tree)
25873     0x11/imm32/alloc-id:fake:payload
25874     1/imm32/is-atom
25875     1/imm32/value:int
25876     0/imm32/left:unused
25877     0/imm32/right:null
25878     0/imm32/right:null
25879 
25880 Type-literal:  # (payload type-tree)
25881     0x11/imm32/alloc-id:fake:payload
25882     1/imm32/is-atom
25883     0/imm32/value:literal
25884     0/imm32/left:unused
25885     0/imm32/right:null
25886     0/imm32/right:null
25887 
25888 Type-addr:  # (payload type-tree)
25889     0x11/imm32/alloc-id:fake:payload
25890     1/imm32/is-atom
25891     2/imm32/value:addr
25892     0/imm32/left:unused
25893     0/imm32/right:null
25894     0/imm32/right:null
25895 
25896 Type-byte:  # (payload type-tree)
25897     0x11/imm32/alloc-id:fake:payload
25898     1/imm32/is-atom
25899     8/imm32/value:byte
25900     0/imm32/left:unused
25901     0/imm32/right:null
25902     0/imm32/right:null
25903 
25904 Type-float:  # (payload type-tree)
25905     0x11/imm32/alloc-id:fake:payload
25906     1/imm32/is-atom
25907     0xf/imm32/value:float
25908     0/imm32/left:unused
25909     0/imm32/right:null
25910     0/imm32/right:null
25911 
25912 == code
25913 emit-subx-primitive:  # out: (addr buffered-file), stmt: (addr stmt), primitive: (addr primitive), err: (addr buffered-file), ed: (addr exit-descriptor)
25914     # . prologue
25915     55/push-ebp
25916     89/<- %ebp 4/r32/esp
25917     # . save registers
25918     50/push-eax
25919     51/push-ecx
25920     # ecx = primitive
25921     8b/-> *(ebp+0x10) 1/r32/ecx
25922     # emit primitive name
25923     (emit-indent *(ebp+8) *Curr-block-depth)
25924     (lookup *(ecx+0x18) *(ecx+0x1c))  # Primitive-subx-name Primitive-subx-name => eax
25925     (write-buffered *(ebp+8) %eax)
25926     # emit rm32 if necessary
25927     (emit-subx-rm32 *(ebp+8) *(ecx+0x20) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # Primitive-subx-rm32
25928     # emit xm32 if necessary
25929     (emit-subx-rm32 *(ebp+8) *(ecx+0x34) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # Primitive-subx-xm32
25930     # emit r32 if necessary
25931     (emit-subx-r32 *(ebp+8) *(ecx+0x24) *(ebp+0xc))  # Primitive-subx-r32
25932     # emit x32 if necessary
25933     (emit-subx-x32 *(ebp+8) *(ecx+0x38) *(ebp+0xc))  # Primitive-subx-x32
25934     # emit imm32 if necessary
25935     (emit-subx-imm32 *(ebp+8) *(ecx+0x28) *(ebp+0xc))  # Primitive-subx-imm32
25936     # emit imm8 if necessary
25937     (emit-subx-imm8 *(ebp+8) *(ecx+0x2c) *(ebp+0xc))  # Primitive-subx-imm8
25938     # emit disp32 if necessary
25939     (emit-subx-disp32 *(ebp+8) *(ecx+0x30) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # Primitive-subx-disp32
25940     (write-buffered *(ebp+8) Newline)
25941 $emit-subx-primitive:end:
25942     # . restore registers
25943     59/pop-to-ecx
25944     58/pop-to-eax
25945     # . epilogue
25946     89/<- %esp 5/r32/ebp
25947     5d/pop-to-ebp
25948     c3/return
25949 
25950 emit-subx-rm32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
25951     # . prologue
25952     55/push-ebp
25953     89/<- %ebp 4/r32/esp
25954     # . save registers
25955     50/push-eax
25956     # if (l == 0) return
25957     81 7/subop/compare *(ebp+0xc) 0/imm32
25958     74/jump-if-= $emit-subx-rm32:end/disp8
25959     # var v/eax: (addr stmt-var)
25960     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # => eax
25961     (emit-subx-var-as-rm32 *(ebp+8) %eax)
25962 $emit-subx-rm32:end:
25963     # . restore registers
25964     58/pop-to-eax
25965     # . epilogue
25966     89/<- %esp 5/r32/ebp
25967     5d/pop-to-ebp
25968     c3/return
25969 
25970 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)
25971     # . prologue
25972     55/push-ebp
25973     89/<- %ebp 4/r32/esp
25974     # . save registers
25975     51/push-ecx
25976     # eax = l
25977     8b/-> *(ebp+0xc) 0/r32/eax
25978     # ecx = stmt
25979     8b/-> *(ebp+8) 1/r32/ecx
25980     # if (l == 1) return stmt->inouts
25981     {
25982       3d/compare-eax-and 1/imm32
25983       75/jump-if-!= break/disp8
25984 $get-stmt-operand-from-arg-location:1:
25985       (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25986       eb/jump $get-stmt-operand-from-arg-location:end/disp8
25987     }
25988     # if (l == 2) return stmt->inouts->next
25989     {
25990       3d/compare-eax-and 2/imm32
25991       75/jump-if-!= break/disp8
25992 $get-stmt-operand-from-arg-location:2:
25993       (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25994       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
25995       eb/jump $get-stmt-operand-from-arg-location:end/disp8
25996     }
25997     # if (l == 3) return stmt->outputs
25998     {
25999       3d/compare-eax-and 3/imm32
26000       75/jump-if-!= break/disp8
26001 $get-stmt-operand-from-arg-location:3:
26002       (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
26003       eb/jump $get-stmt-operand-from-arg-location:end/disp8
26004     }
26005     # abort
26006     e9/jump $get-stmt-operand-from-arg-location:abort/disp32
26007 $get-stmt-operand-from-arg-location:end:
26008     # . restore registers
26009     59/pop-to-ecx
26010     # . epilogue
26011     89/<- %esp 5/r32/ebp
26012     5d/pop-to-ebp
26013     c3/return
26014 
26015 $get-stmt-operand-from-arg-location:abort:
26016     # error("invalid arg-location " eax)
26017     (write-buffered *(ebp+0x10) "invalid arg-location ")
26018     (write-int32-hex-buffered *(ebp+0x10) %eax)
26019     (write-buffered *(ebp+0x10) Newline)
26020     (flush *(ebp+0x10))
26021     (stop *(ebp+0x14) 1)
26022     # never gets here
26023 
26024 emit-subx-r32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
26025     # . prologue
26026     55/push-ebp
26027     89/<- %ebp 4/r32/esp
26028     # . save registers
26029     50/push-eax
26030     51/push-ecx
26031     # if (l == 0) return
26032     81 7/subop/compare *(ebp+0xc) 0/imm32
26033     0f 84/jump-if-= $emit-subx-r32:end/disp32
26034     # var v/eax: (addr stmt-var)
26035     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
26036     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
26037     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
26038 #?     (write-buffered Stderr "looking up ")
26039 #?     (write-buffered Stderr %eax)
26040 #?     (write-buffered Stderr Newline)
26041 #?     (flush Stderr)
26042     (maybe-get Mu-registers %eax 0xc)  # => eax: (addr register-index)
26043     (write-buffered *(ebp+8) Space)
26044     (write-int32-hex-buffered *(ebp+8) *eax)
26045     (write-buffered *(ebp+8) "/r32")
26046 $emit-subx-r32:end:
26047     # . restore registers
26048     59/pop-to-ecx
26049     58/pop-to-eax
26050     # . epilogue
26051     89/<- %esp 5/r32/ebp
26052     5d/pop-to-ebp
26053     c3/return
26054 
26055 emit-subx-x32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
26056     # . prologue
26057     55/push-ebp
26058     89/<- %ebp 4/r32/esp
26059     # . save registers
26060     50/push-eax
26061     51/push-ecx
26062     # if (l == 0) return
26063     81 7/subop/compare *(ebp+0xc) 0/imm32
26064     0f 84/jump-if-= $emit-subx-x32:end/disp32
26065     # var v/eax: (addr stmt-var)
26066     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
26067     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
26068     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
26069 #?     (write-buffered Stderr "looking up ")
26070 #?     (write-buffered Stderr %eax)
26071 #?     (write-buffered Stderr Newline)
26072 #?     (flush Stderr)
26073     (maybe-get Mu-registers %eax 0xc)  # => eax: (addr register-index)
26074     (write-buffered *(ebp+8) Space)
26075     (write-int32-hex-buffered *(ebp+8) *eax)
26076     (write-buffered *(ebp+8) "/x32")
26077 $emit-subx-x32:end:
26078     # . restore registers
26079     59/pop-to-ecx
26080     58/pop-to-eax
26081     # . epilogue
26082     89/<- %esp 5/r32/ebp
26083     5d/pop-to-ebp
26084     c3/return
26085 
26086 emit-subx-imm32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
26087     # . prologue
26088     55/push-ebp
26089     89/<- %ebp 4/r32/esp
26090     # . save registers
26091     50/push-eax
26092     51/push-ecx
26093     # if (l == 0) return
26094     81 7/subop/compare *(ebp+0xc) 0/imm32
26095     0f 84/jump-if-= $emit-subx-imm32:end/disp32
26096     # var v/eax: (handle var)
26097     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
26098     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
26099     (lookup *eax *(eax+4))  # Var-name Var-name => eax
26100     (write-buffered *(ebp+8) Space)
26101     (write-buffered *(ebp+8) %eax)
26102     (write-buffered *(ebp+8) "/imm32")
26103 $emit-subx-imm32:end:
26104     # . restore registers
26105     59/pop-to-ecx
26106     58/pop-to-eax
26107     # . epilogue
26108     89/<- %esp 5/r32/ebp
26109     5d/pop-to-ebp
26110     c3/return
26111 
26112 emit-subx-imm8:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
26113     # . prologue
26114     55/push-ebp
26115     89/<- %ebp 4/r32/esp
26116     # . save registers
26117     50/push-eax
26118     51/push-ecx
26119     # if (l == 0) return
26120     81 7/subop/compare *(ebp+0xc) 0/imm32
26121     0f 84/jump-if-= $emit-subx-imm32:end/disp32
26122     # var v/eax: (handle var)
26123     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
26124     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
26125     (lookup *eax *(eax+4))  # Var-name Var-name => eax
26126     (write-buffered *(ebp+8) Space)
26127     (write-buffered *(ebp+8) %eax)
26128     (write-buffered *(ebp+8) "/imm8")
26129 $emit-subx-imm8:end:
26130     # . restore registers
26131     59/pop-to-ecx
26132     58/pop-to-eax
26133     # . epilogue
26134     89/<- %esp 5/r32/ebp
26135     5d/pop-to-ebp
26136     c3/return
26137 
26138 emit-subx-disp32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
26139     # . prologue
26140     55/push-ebp
26141     89/<- %ebp 4/r32/esp
26142     # . save registers
26143     50/push-eax
26144     51/push-ecx
26145     # if (location == 0) return
26146     81 7/subop/compare *(ebp+0xc) 0/imm32
26147     0f 84/jump-if-= $emit-subx-disp32:end/disp32
26148     # var v/eax: (addr stmt-var)
26149     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # => eax
26150     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
26151     (lookup *eax *(eax+4))  # Var-name Var-name => eax
26152     (write-buffered *(ebp+8) Space)
26153     (write-buffered *(ebp+8) %eax)
26154     # hack: if instruction operation starts with "break", emit ":break"
26155     # var name/ecx: (addr array byte) = lookup(stmt->operation)
26156     8b/-> *(ebp+0x10) 0/r32/eax
26157     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
26158     89/<- %ecx 0/r32/eax
26159     {
26160       (string-starts-with? %ecx "break")  # => eax
26161       3d/compare-eax-and 0/imm32/false
26162       74/jump-if-= break/disp8
26163       (write-buffered *(ebp+8) ":break")
26164     }
26165     # hack: if instruction operation starts with "loop", emit ":loop"
26166     {
26167       (string-starts-with? %ecx "loop")  # => eax
26168       3d/compare-eax-and 0/imm32/false
26169       74/jump-if-= break/disp8
26170       (write-buffered *(ebp+8) ":loop")
26171     }
26172     (write-buffered *(ebp+8) "/disp32")
26173 $emit-subx-disp32:end:
26174     # . restore registers
26175     59/pop-to-ecx
26176     58/pop-to-eax
26177     # . epilogue
26178     89/<- %esp 5/r32/ebp
26179     5d/pop-to-ebp
26180     c3/return
26181 
26182 emit-call:  # out: (addr buffered-file), stmt: (addr stmt)
26183     # . prologue
26184     55/push-ebp
26185     89/<- %ebp 4/r32/esp
26186     # . save registers
26187     50/push-eax
26188     51/push-ecx
26189     #
26190     (emit-indent *(ebp+8) *Curr-block-depth)
26191     (write-buffered *(ebp+8) "(")
26192     # ecx = stmt
26193     8b/-> *(ebp+0xc) 1/r32/ecx
26194     # - emit function name
26195     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
26196     (write-buffered *(ebp+8) %eax)
26197     # - emit arguments
26198     # var curr/eax: (addr stmt-var) = lookup(stmt->inouts)
26199     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
26200     {
26201       # if (curr == null) break
26202       3d/compare-eax-and 0/imm32
26203       74/jump-if-= break/disp8
26204       #
26205       (emit-subx-call-operand *(ebp+8) %eax)
26206       # curr = lookup(curr->next)
26207       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
26208       eb/jump loop/disp8
26209     }
26210     #
26211     (write-buffered *(ebp+8) ")\n")
26212 $emit-call:end:
26213     # . restore registers
26214     59/pop-to-ecx
26215     58/pop-to-eax
26216     # . epilogue
26217     89/<- %esp 5/r32/ebp
26218     5d/pop-to-ebp
26219     c3/return
26220 
26221 emit-subx-call-operand:  # out: (addr buffered-file), s: (addr stmt-var)
26222     # shares code with emit-subx-var-as-rm32
26223     # . prologue
26224     55/push-ebp
26225     89/<- %ebp 4/r32/esp
26226     # . save registers
26227     50/push-eax
26228     51/push-ecx
26229     56/push-esi
26230     # ecx = s
26231     8b/-> *(ebp+0xc) 1/r32/ecx
26232     # var operand/esi: (addr var) = lookup(s->value)
26233     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
26234     89/<- %esi 0/r32/eax
26235     # if (operand->register && !s->is-deref?) emit "%__"
26236     {
26237 $emit-subx-call-operand:check-for-register-direct:
26238       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
26239       74/jump-if-= break/disp8
26240       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
26241       75/jump-if-!= break/disp8
26242 $emit-subx-call-operand:register-direct:
26243       (write-buffered *(ebp+8) " %")
26244       (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
26245       (write-buffered *(ebp+8) %eax)
26246       e9/jump $emit-subx-call-operand:end/disp32
26247     }
26248     # else if (operand->register && s->is-deref?) emit "*__"
26249     {
26250 $emit-subx-call-operand:check-for-register-indirect:
26251       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
26252       74/jump-if-= break/disp8
26253       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
26254       74/jump-if-= break/disp8
26255 $emit-subx-call-operand:register-indirect:
26256       (emit-subx-call-operand-register-indirect *(ebp+8) %esi)
26257       e9/jump $emit-subx-call-operand:end/disp32
26258     }
26259     # else if (operand->stack-offset) emit "*(ebp+__)"
26260     {
26261       81 7/subop/compare *(esi+0x14) 0/imm32  # Var-offset
26262       74/jump-if-= break/disp8
26263 $emit-subx-call-operand:stack:
26264       (emit-subx-call-operand-stack *(ebp+8) %esi)
26265       e9/jump $emit-subx-call-operand:end/disp32
26266     }
26267     # else if (operand->type == literal) emit "__"
26268     {
26269       (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
26270       81 7/subop/compare *(eax+4) 0/imm32  # Type-tree-left
26271       75/jump-if-!= break/disp8
26272 $emit-subx-call-operand:literal:
26273       (write-buffered *(ebp+8) Space)
26274       (lookup *esi *(esi+4))  # Var-name Var-name => eax
26275       (write-buffered *(ebp+8) %eax)
26276     }
26277 $emit-subx-call-operand:end:
26278     # . restore registers
26279     5e/pop-to-esi
26280     59/pop-to-ecx
26281     58/pop-to-eax
26282     # . epilogue
26283     89/<- %esp 5/r32/ebp
26284     5d/pop-to-ebp
26285     c3/return
26286 
26287 emit-subx-call-operand-register-indirect:  # out: (addr buffered-file), v: (addr var)
26288     # . prologue
26289     55/push-ebp
26290     89/<- %ebp 4/r32/esp
26291     # . save registers
26292     50/push-eax
26293     51/push-ecx
26294     56/push-esi
26295     # esi = v
26296     8b/-> *(ebp+0xc) 6/r32/esi
26297     # var size/ecx: int = size-of-deref(v)
26298     (size-of-deref %esi)  # => eax
26299     89/<- %ecx 0/r32/eax
26300     # var reg-name/esi: (addr array byte) = lookup(v->register)
26301     (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
26302     89/<- %esi 0/r32/eax
26303     # TODO: assert size is a multiple of 4
26304     # var i/eax: int = 0
26305     b8/copy-to-eax 0/imm32
26306     {
26307 $emit-subx-call-operand-register-indirect:loop:
26308       # if (i >= size) break
26309       39/compare %eax 1/r32/ecx
26310       7d/jump-if->= break/disp8
26311       # emit " *(" v->register "+" i ")"
26312       (write-buffered *(ebp+8) " *(")
26313       (write-buffered *(ebp+8) %esi)
26314       (write-buffered *(ebp+8) "+")
26315       (write-int32-hex-buffered *(ebp+8) %eax)
26316       (write-buffered *(ebp+8) ")")
26317       # i += 4
26318       05/add-to-eax 4/imm32
26319       #
26320       eb/jump loop/disp8
26321     }
26322 $emit-subx-call-operand-register-indirect:end:
26323     # . restore registers
26324     5e/pop-to-esi
26325     59/pop-to-ecx
26326     58/pop-to-eax
26327     # . epilogue
26328     89/<- %esp 5/r32/ebp
26329     5d/pop-to-ebp
26330     c3/return
26331 
26332 emit-subx-call-operand-stack:  # out: (addr buffered-file), v: (addr var)
26333     # . prologue
26334     55/push-ebp
26335     89/<- %ebp 4/r32/esp
26336     # . save registers
26337     50/push-eax
26338     51/push-ecx
26339     56/push-esi
26340     # esi = v
26341     8b/-> *(ebp+0xc) 6/r32/esi
26342     # var curr/ecx: int = v->offset
26343     8b/-> *(esi+0x14) 1/r32/ecx  # Var-offset
26344     # var max/eax: int = v->offset + size-of(v)
26345     (size-of %esi)  # => eax
26346     # TODO: assert size is a multiple of 4
26347     01/add-to %eax 1/r32/ecx
26348     {
26349 $emit-subx-call-operand-stack:loop:
26350       # if (curr >= max) break
26351       39/compare %ecx 0/r32/eax
26352       7d/jump-if->= break/disp8
26353       # emit " *(ebp+" curr ")"
26354       (write-buffered *(ebp+8) " *(ebp+")
26355       (write-int32-hex-buffered *(ebp+8) %ecx)
26356       (write-buffered *(ebp+8) ")")
26357       # i += 4
26358       81 0/subop/add %ecx 4/imm32
26359       #
26360       eb/jump loop/disp8
26361     }
26362 $emit-subx-call-operand-stack:end:
26363     # . restore registers
26364     5e/pop-to-esi
26365     59/pop-to-ecx
26366     58/pop-to-eax
26367     # . epilogue
26368     89/<- %esp 5/r32/ebp
26369     5d/pop-to-ebp
26370     c3/return
26371 
26372 emit-subx-var-as-rm32:  # out: (addr buffered-file), s: (addr stmt-var)
26373     # . prologue
26374     55/push-ebp
26375     89/<- %ebp 4/r32/esp
26376     # . save registers
26377     50/push-eax
26378     51/push-ecx
26379     56/push-esi
26380     # ecx = s
26381     8b/-> *(ebp+0xc) 1/r32/ecx
26382     # var operand/esi: (addr var) = lookup(s->value)
26383     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
26384     89/<- %esi 0/r32/eax
26385     # if (operand->register && s->is-deref?) emit "*__"
26386     {
26387 $emit-subx-var-as-rm32:check-for-register-indirect:
26388       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
26389       74/jump-if-= break/disp8
26390       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
26391       74/jump-if-= break/disp8
26392 $emit-subx-var-as-rm32:register-indirect:
26393       (write-buffered *(ebp+8) " *")
26394       (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
26395       (write-buffered *(ebp+8) %eax)
26396       e9/jump $emit-subx-var-as-rm32:end/disp32
26397     }
26398     # if (operand->register && !s->is-deref?) emit "%__"
26399     {
26400 $emit-subx-var-as-rm32:check-for-register-direct:
26401       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
26402       74/jump-if-= break/disp8
26403       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
26404       75/jump-if-!= break/disp8
26405 $emit-subx-var-as-rm32:register-direct:
26406       (write-buffered *(ebp+8) " %")
26407       (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
26408       (write-buffered *(ebp+8) %eax)
26409       e9/jump $emit-subx-var-as-rm32:end/disp32
26410     }
26411     # else if (operand->stack-offset) emit "*(ebp+__)"
26412     {
26413       81 7/subop/compare *(esi+0x14) 0/imm32  # Var-offset
26414       74/jump-if-= break/disp8
26415 $emit-subx-var-as-rm32:stack:
26416       (write-buffered *(ebp+8) Space)
26417       (write-buffered *(ebp+8) "*(ebp+")
26418       (write-int32-hex-buffered *(ebp+8) *(esi+0x14))  # Var-offset
26419       (write-buffered *(ebp+8) ")")
26420     }
26421 $emit-subx-var-as-rm32:end:
26422     # . restore registers
26423     5e/pop-to-esi
26424     59/pop-to-ecx
26425     58/pop-to-eax
26426     # . epilogue
26427     89/<- %esp 5/r32/ebp
26428     5d/pop-to-ebp
26429     c3/return
26430 
26431 find-matching-primitive:  # primitives: (addr primitive), stmt: (addr stmt) -> result/eax: (addr primitive)
26432     # . prologue
26433     55/push-ebp
26434     89/<- %ebp 4/r32/esp
26435     # . save registers
26436     51/push-ecx
26437     # var curr/ecx: (addr primitive) = primitives
26438     8b/-> *(ebp+8) 1/r32/ecx
26439     {
26440 $find-matching-primitive:loop:
26441       # if (curr == null) break
26442       81 7/subop/compare %ecx 0/imm32
26443       74/jump-if-= break/disp8
26444       # if match(curr, stmt) return curr
26445       {
26446         (mu-stmt-matches-primitive? *(ebp+0xc) %ecx)  # => eax
26447         3d/compare-eax-and 0/imm32/false
26448         74/jump-if-= break/disp8
26449         89/<- %eax 1/r32/ecx
26450         eb/jump $find-matching-primitive:end/disp8
26451       }
26452 $find-matching-primitive:next-primitive:
26453       # curr = curr->next
26454       (lookup *(ecx+0x3c) *(ecx+0x40))  # Primitive-next Primitive-next => eax
26455       89/<- %ecx 0/r32/eax
26456       #
26457       e9/jump loop/disp32
26458     }
26459     # return null
26460     b8/copy-to-eax 0/imm32
26461 $find-matching-primitive:end:
26462     # . restore registers
26463     59/pop-to-ecx
26464     # . epilogue
26465     89/<- %esp 5/r32/ebp
26466     5d/pop-to-ebp
26467     c3/return
26468 
26469 mu-stmt-matches-primitive?:  # stmt: (addr stmt), primitive: (addr primitive) -> result/eax: boolean
26470     # A mu stmt matches a primitive if the name matches, all the inout vars
26471     # match, and all the output vars match.
26472     # Vars match if types match and registers match.
26473     # In addition, a stmt output matches a primitive's output if types match
26474     # and the primitive has a wildcard register.
26475     # . prologue
26476     55/push-ebp
26477     89/<- %ebp 4/r32/esp
26478     # . save registers
26479     51/push-ecx
26480     52/push-edx
26481     53/push-ebx
26482     56/push-esi
26483     57/push-edi
26484     # ecx = stmt
26485     8b/-> *(ebp+8) 1/r32/ecx
26486     # edx = primitive
26487     8b/-> *(ebp+0xc) 2/r32/edx
26488     {
26489 $mu-stmt-matches-primitive?:check-name:
26490       # if (primitive->name != stmt->operation) return false
26491       # . var esi: (addr array byte) = lookup(stmt->operation)
26492       (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
26493       89/<- %esi 0/r32/eax
26494       # . var edi: (addr array byte) = lookup(primitive->name)
26495       (lookup *edx *(edx+4))  # Primitive-name Primitive-name => eax
26496 #?       (write-buffered Stderr %eax)
26497 #?       (write-buffered Stderr Newline)
26498 #?       (flush Stderr)
26499       89/<- %edi 0/r32/eax
26500       (string-equal? %esi %edi)  # => eax
26501       3d/compare-eax-and 0/imm32/false
26502       75/jump-if-!= break/disp8
26503       b8/copy-to-eax 0/imm32
26504       e9/jump $mu-stmt-matches-primitive?:end/disp32
26505     }
26506     # var curr/esi: (addr stmt-var) = lookup(stmt->inouts)
26507     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
26508     89/<- %esi 0/r32/eax
26509     # var curr2/edi: (addr list var) = lookup(primitive->inouts)
26510     (lookup *(edx+8) *(edx+0xc))  # Primitive-inouts Primitive-inouts => eax
26511     89/<- %edi 0/r32/eax
26512     {
26513 $mu-stmt-matches-primitive?:inouts-loop:
26514       # if (curr == 0 && curr2 == 0) move on to check outputs
26515       {
26516 $mu-stmt-matches-primitive?:check-both-inouts-null:
26517         81 7/subop/compare %esi 0/imm32
26518         75/jump-if-!= break/disp8
26519 $mu-stmt-matches-primitive?:stmt-inout-null:
26520         81 7/subop/compare %edi 0/imm32
26521         0f 84/jump-if-= $mu-stmt-matches-primitive?:check-outputs/disp32
26522 $mu-stmt-matches-primitive?:stmt-inout-null-and-prim-inout-not-null:
26523         # return false
26524         b8/copy-to-eax 0/imm32/false
26525         e9/jump $mu-stmt-matches-primitive?:end/disp32
26526       }
26527       # if (curr2 == 0) return false
26528       {
26529 $mu-stmt-matches-primitive?:check-prim-inout-null:
26530         81 7/subop/compare %edi 0/imm32
26531         75/jump-if-!= break/disp8
26532 $mu-stmt-matches-primitive?:prim-inout-null:
26533         b8/copy-to-eax 0/imm32/false
26534         e9/jump $mu-stmt-matches-primitive?:end/disp32
26535       }
26536       # if (curr != curr2) return false
26537       {
26538 $mu-stmt-matches-primitive?:check-inouts-match:
26539         (lookup *edi *(edi+4))  # List-value List-value => eax
26540         (operand-matches-primitive? %esi %eax)  # => eax
26541         3d/compare-eax-and 0/imm32/false
26542         75/jump-if-!= break/disp8
26543 $mu-stmt-matches-primitive?:inouts-match:
26544         b8/copy-to-eax 0/imm32/false
26545         e9/jump $mu-stmt-matches-primitive?:end/disp32
26546       }
26547 $mu-stmt-matches-primitive?:next-inout:
26548       # curr = lookup(curr->next)
26549       (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
26550       89/<- %esi 0/r32/eax
26551       # curr2 = lookup(curr2->next)
26552       (lookup *(edi+8) *(edi+0xc))  # List-next List-next => eax
26553       89/<- %edi 0/r32/eax
26554       #
26555       e9/jump loop/disp32
26556     }
26557 $mu-stmt-matches-primitive?:check-outputs:
26558     # var curr/esi: (addr stmt-var) = lookup(stmt->outputs)
26559     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
26560     89/<- %esi 0/r32/eax
26561     # var curr2/edi: (addr list var) = lookup(primitive->outputs)
26562     (lookup *(edx+0x10) *(edx+0x14))  # Primitive-outputs Primitive-outputs => eax
26563     89/<- %edi 0/r32/eax
26564     {
26565 $mu-stmt-matches-primitive?:outputs-loop:
26566       # if (curr == 0) return (curr2 == 0)
26567       {
26568 $mu-stmt-matches-primitive?:check-both-outputs-null:
26569         81 7/subop/compare %esi 0/imm32
26570         75/jump-if-!= break/disp8
26571         {
26572 $mu-stmt-matches-primitive?:stmt-output-null:
26573           81 7/subop/compare %edi 0/imm32
26574           75/jump-if-!= break/disp8
26575 $mu-stmt-matches-primitive?:both-outputs-null:
26576           # return true
26577           b8/copy-to-eax 1/imm32
26578           e9/jump $mu-stmt-matches-primitive?:end/disp32
26579         }
26580 $mu-stmt-matches-primitive?:stmt-output-null-and-prim-output-not-null:
26581         # return false
26582         b8/copy-to-eax 0/imm32
26583         e9/jump $mu-stmt-matches-primitive?:end/disp32
26584       }
26585       # if (curr2 == 0) return false
26586       {
26587 $mu-stmt-matches-primitive?:check-prim-output-null:
26588         81 7/subop/compare %edi 0/imm32
26589         75/jump-if-!= break/disp8
26590 $mu-stmt-matches-primitive?:prim-output-is-null:
26591         b8/copy-to-eax 0/imm32
26592         e9/jump $mu-stmt-matches-primitive?:end/disp32
26593       }
26594       # if (curr != curr2) return false
26595       {
26596 $mu-stmt-matches-primitive?:check-outputs-match:
26597         (lookup *edi *(edi+4))  # List-value List-value => eax
26598         (operand-matches-primitive? %esi %eax)  # => eax
26599         3d/compare-eax-and 0/imm32/false
26600         75/jump-if-!= break/disp8
26601 $mu-stmt-matches-primitive?:outputs-match:
26602         b8/copy-to-eax 0/imm32
26603         e9/jump $mu-stmt-matches-primitive?:end/disp32
26604       }
26605 $mu-stmt-matches-primitive?:next-output:
26606       # curr = lookup(curr->next)
26607       (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
26608       89/<- %esi 0/r32/eax
26609       # curr2 = lookup(curr2->next)
26610       (lookup *(edi+8) *(edi+0xc))  # List-next List-next => eax
26611       89/<- %edi 0/r32/eax
26612       #
26613       e9/jump loop/disp32
26614     }
26615 $mu-stmt-matches-primitive?:return-true:
26616     b8/copy-to-eax 1/imm32
26617 $mu-stmt-matches-primitive?:end:
26618     # . restore registers
26619     5f/pop-to-edi
26620     5e/pop-to-esi
26621     5b/pop-to-ebx
26622     5a/pop-to-edx
26623     59/pop-to-ecx
26624     # . epilogue
26625     89/<- %esp 5/r32/ebp
26626     5d/pop-to-ebp
26627     c3/return
26628 
26629 operand-matches-primitive?:  # s: (addr stmt-var), prim-var: (addr var) -> result/eax: boolean
26630     # . prologue
26631     55/push-ebp
26632     89/<- %ebp 4/r32/esp
26633     # . save registers
26634     51/push-ecx
26635     52/push-edx
26636     53/push-ebx
26637     56/push-esi
26638     57/push-edi
26639     # ecx = s
26640     8b/-> *(ebp+8) 1/r32/ecx
26641     # var var/esi: (addr var) = lookup(s->value)
26642     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
26643     89/<- %esi 0/r32/eax
26644     # edi = prim-var
26645     8b/-> *(ebp+0xc) 7/r32/edi
26646 $operand-matches-primitive?:check-type:
26647     # if !category-match?(var->type, prim-var->type) return false
26648     # . var vtype/ebx: (addr type-tree) = lookup(var->type)
26649     (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
26650     89/<- %ebx 0/r32/eax
26651     # . if s is deref, vtype = vtype->right
26652     {
26653       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
26654       74/jump-if-= break/disp8
26655 $operand-matches-primitive?:is-deref:
26656       # . var t/eax: (addr type)
26657       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
26658       # . if !t->is-atom? t = t->left
26659       81 7/subop/compare *eax 0/imm32/false
26660       {
26661         75/jump-if-!= break/disp8
26662         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
26663       }
26664       # .
26665       89/<- %ebx 0/r32/eax
26666     }
26667     # . var ptype/eax: (addr type-tree) = lookup(prim-var->type)
26668     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
26669     (subx-type-category-match? %ebx %eax)  # => eax
26670     3d/compare-eax-and 0/imm32/false
26671     0f 84/jump-if-= $operand-matches-primitive?:return-false/disp32
26672     {
26673 $operand-matches-primitive?:check-register:
26674       # if prim-var is in memory and var is in register but dereference, match
26675       {
26676         81 7/subop/compare *(edi+0x18) 0/imm32  # Var-register
26677         0f 85/jump-if-!= break/disp32
26678         81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
26679         74/jump-if-= break/disp8
26680         81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
26681         74/jump-if-= break/disp8
26682 $operand-matches-primitive?:var-deref-match:
26683         e9/jump $operand-matches-primitive?:return-true/disp32
26684       }
26685       # if prim-var is in register and var is in register but dereference, no match
26686       {
26687         81 7/subop/compare *(edi+0x18) 0/imm32  # Var-register
26688         0f 84/jump-if-= break/disp32
26689         81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
26690         0f 84/jump-if-= break/disp32
26691         81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
26692         74/jump-if-= break/disp8
26693 $operand-matches-primitive?:var-deref-no-match:
26694         e9/jump $operand-matches-primitive?:return-false/disp32
26695       }
26696       # return false if var->register doesn't match prim-var->register
26697       {
26698         # if register addresses are equal, it's a match
26699         # var vreg/ebx: (addr array byte) = lookup(var->register)
26700         (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
26701         89/<- %ebx 0/r32/eax
26702         # var preg/ecx: (addr array byte) = lookup(prim-var->register)
26703         (lookup *(edi+0x18) *(edi+0x1c))  # Var-register Var-register => eax
26704         89/<- %ecx 0/r32/eax
26705         # if (vreg == preg) break
26706         39/compare %ecx 3/r32/ebx
26707         74/jump-if-= break/disp8
26708 $operand-matches-primitive?:var-register-no-match:
26709         # if either address is 0, return false
26710         81 7/subop/compare %ebx 0/imm32
26711         74/jump-if-=  $operand-matches-primitive?:return-false/disp8
26712         81 7/subop/compare %ecx 0/imm32
26713         74/jump-if-=  $operand-matches-primitive?:return-false/disp8
26714         # if prim-var->register is wildcard, it's a match
26715         (string-equal? %ecx "*")  # Any-register => eax
26716         3d/compare-eax-and 0/imm32/false
26717         75/jump-if-!= break/disp8
26718 $operand-matches-primitive?:wildcard-no-match:
26719         # if string contents aren't equal, return false
26720         (string-equal? %ecx %ebx)  # => eax
26721         3d/compare-eax-and 0/imm32/false
26722         74/jump-if-= $operand-matches-primitive?:return-false/disp8
26723       }
26724     }
26725 $operand-matches-primitive?:return-true:
26726     b8/copy-to-eax 1/imm32/true
26727     eb/jump $operand-matches-primitive?:end/disp8
26728 $operand-matches-primitive?:return-false:
26729     b8/copy-to-eax 0/imm32/false
26730 $operand-matches-primitive?:end:
26731     # . restore registers
26732     5f/pop-to-edi
26733     5e/pop-to-esi
26734     5b/pop-to-ebx
26735     5a/pop-to-edx
26736     59/pop-to-ecx
26737     # . epilogue
26738     89/<- %esp 5/r32/ebp
26739     5d/pop-to-ebp
26740     c3/return
26741 
26742 find-matching-function:  # functions: (addr function), stmt: (addr stmt) -> result/eax: (addr function)
26743     # . prologue
26744     55/push-ebp
26745     89/<- %ebp 4/r32/esp
26746     # . save registers
26747     51/push-ecx
26748     # var curr/ecx: (handle function) = functions
26749     8b/-> *(ebp+8) 1/r32/ecx
26750     {
26751       # if (curr == null) break
26752       81 7/subop/compare %ecx 0/imm32
26753       74/jump-if-= break/disp8
26754 #?       (write-buffered Stderr "iter\n")
26755 #?       (flush Stderr)
26756       # if match(stmt, curr) return curr
26757       {
26758         (mu-stmt-matches-function? *(ebp+0xc) %ecx)  # => eax
26759         3d/compare-eax-and 0/imm32/false
26760         74/jump-if-= break/disp8
26761         89/<- %eax 1/r32/ecx
26762         eb/jump $find-matching-function:end/disp8
26763       }
26764       # curr = curr->next
26765       (lookup *(ecx+0x20) *(ecx+0x24))  # Function-next Function-next => eax
26766       89/<- %ecx 0/r32/eax
26767       #
26768       eb/jump loop/disp8
26769     }
26770     # return null
26771     b8/copy-to-eax 0/imm32
26772 $find-matching-function:end:
26773     # . restore registers
26774     59/pop-to-ecx
26775     # . epilogue
26776     89/<- %esp 5/r32/ebp
26777     5d/pop-to-ebp
26778     c3/return
26779 
26780 # Just compare names; user-defined functions don't support overloading yet.
26781 mu-stmt-matches-function?:  # stmt: (addr stmt1), function: (addr function) -> result/eax: boolean
26782     # . prologue
26783     55/push-ebp
26784     89/<- %ebp 4/r32/esp
26785     # . save registers
26786     51/push-ecx
26787     # return function->name == stmt->operation
26788     # ecx = lookup(stmt->operation)
26789     8b/-> *(ebp+8) 0/r32/eax
26790     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
26791     89/<- %ecx 0/r32/eax
26792     # eax = lookup(function->name)
26793     8b/-> *(ebp+0xc) 0/r32/eax
26794     (lookup *eax *(eax+4))  # Function-name Function-name => eax
26795     (string-equal? %eax %ecx)  # => eax
26796 $mu-stmt-matches-function?:end:
26797     # . restore registers
26798     59/pop-to-ecx
26799     # . epilogue
26800     89/<- %esp 5/r32/ebp
26801     5d/pop-to-ebp
26802     c3/return
26803 
26804 # Type-checking happens elsewhere. This method is for selecting between
26805 # primitives.
26806 subx-type-category-match?:  # a: (addr type-tree), b: (addr type-tree) -> result/eax: boolean
26807     # . prologue
26808     55/push-ebp
26809     89/<- %ebp 4/r32/esp
26810     # . save registers
26811     51/push-ecx
26812     # var cata/ecx: int = type-category(a)
26813     (type-category *(ebp+8))  # => eax
26814     89/<- %ecx 0/r32/eax
26815     # var catb/eax: int = type-category(b)
26816     (type-category *(ebp+0xc))  # => eax
26817     # return cata == catb
26818     39/compare %eax 1/r32/ecx
26819     0f 94/set-byte-if-= %al
26820     81 4/subop/and %eax 0xff/imm32
26821 $subx-type-category-match?:end:
26822     # . restore registers
26823     59/pop-to-ecx
26824     # . epilogue
26825     89/<- %esp 5/r32/ebp
26826     5d/pop-to-ebp
26827     c3/return
26828 
26829 type-category:  # a: (addr type-tree) -> result/eax: int
26830     # . prologue
26831     55/push-ebp
26832     89/<- %ebp 4/r32/esp
26833     # . save registers
26834     51/push-ecx
26835     # var lit?/ecx: boolean = is-literal-type?(a)
26836     (is-simple-mu-type? *(ebp+8) 0)  # => eax
26837     89/<- %ecx 0/r32/eax
26838     # var float?/eax: int = is-float?(a)
26839     (is-simple-mu-type? *(ebp+8) 0xf)  # => eax
26840     # set bits for lit? and float?
26841     c1/shift 4/subop/left %ecx 1/imm8
26842     09/or %eax 1/r32/ecx
26843 $type-category:end:
26844     # . restore registers
26845     59/pop-to-ecx
26846     # . epilogue
26847     89/<- %esp 5/r32/ebp
26848     5d/pop-to-ebp
26849     c3/return
26850 
26851 is-simple-mu-type?:  # a: (addr type-tree), n: type-id -> result/eax: boolean
26852     # . prologue
26853     55/push-ebp
26854     89/<- %ebp 4/r32/esp
26855     # . save registers
26856     51/push-ecx
26857     # ecx = n
26858     8b/-> *(ebp+0xc) 1/r32/ecx
26859     # return (a->value == n)
26860     8b/-> *(ebp+8) 0/r32/eax
26861     39/compare *(eax+4) 1/r32/ecx  # Type-tree-value
26862     0f 94/set-byte-if-= %al
26863     81 4/subop/and %eax 0xff/imm32
26864 $is-simple-mu-type?:end:
26865     # . restore registers
26866     59/pop-to-ecx
26867     # . epilogue
26868     89/<- %esp 5/r32/ebp
26869     5d/pop-to-ebp
26870     c3/return
26871 
26872 is-mu-addr-type?:  # a: (addr type-tree) -> result/eax: boolean
26873     # . prologue
26874     55/push-ebp
26875     89/<- %ebp 4/r32/esp
26876     # eax = a
26877     8b/-> *(ebp+8) 0/r32/eax
26878     # if (!a->is-atom?) a = a->left
26879     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
26880     {
26881       75/jump-if-!= break/disp8
26882       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
26883     }
26884     # return (a->value == addr)
26885     81 7/subop/compare *(eax+4) 2/imm32/addr  # Type-tree-value
26886     0f 94/set-byte-if-= %al
26887     81 4/subop/and %eax 0xff/imm32
26888 $is-mu-addr-type?:end:
26889     # . epilogue
26890     89/<- %esp 5/r32/ebp
26891     5d/pop-to-ebp
26892     c3/return
26893 
26894 is-mu-array-type?:  # a: (addr type-tree) -> result/eax: boolean
26895     # . prologue
26896     55/push-ebp
26897     89/<- %ebp 4/r32/esp
26898     # eax = a
26899     8b/-> *(ebp+8) 0/r32/eax
26900     # if (!a->is-atom?) a = a->left
26901     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
26902     {
26903       75/jump-if-!= break/disp8
26904       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
26905     }
26906     # return (a->value == array)
26907     81 7/subop/compare *(eax+4) 3/imm32/array  # Type-tree-value
26908     0f 94/set-byte-if-= %al
26909     81 4/subop/and %eax 0xff/imm32
26910 $is-mu-array-type?:end:
26911     # . epilogue
26912     89/<- %esp 5/r32/ebp
26913     5d/pop-to-ebp
26914     c3/return
26915 
26916 is-mu-stream-type?:  # a: (addr type-tree) -> result/eax: boolean
26917     # . prologue
26918     55/push-ebp
26919     89/<- %ebp 4/r32/esp
26920     # eax = a
26921     8b/-> *(ebp+8) 0/r32/eax
26922     # if (!a->is-atom?) a = a->left
26923     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
26924     {
26925       75/jump-if-!= break/disp8
26926       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
26927     }
26928     # return (a->value == stream)
26929     81 7/subop/compare *(eax+4) 0xb/imm32/stream  # Type-tree-value
26930     0f 94/set-byte-if-= %al
26931     81 4/subop/and %eax 0xff/imm32
26932 $is-mu-stream-type?:end:
26933     # . epilogue
26934     89/<- %esp 5/r32/ebp
26935     5d/pop-to-ebp
26936     c3/return
26937 
26938 test-emit-subx-stmt-primitive:
26939     # Primitive operation on a variable on the stack.
26940     #   increment foo
26941     # =>
26942     #   ff 0/subop/increment *(ebp-8)
26943     #
26944     # There's a variable on the var stack as follows:
26945     #   name: 'foo'
26946     #   type: int
26947     #   stack-offset: -8
26948     #
26949     # There's a primitive with this info:
26950     #   name: 'increment'
26951     #   inouts: int/mem
26952     #   value: 'ff 0/subop/increment'
26953     #
26954     # . prologue
26955     55/push-ebp
26956     89/<- %ebp 4/r32/esp
26957     # setup
26958     (clear-stream _test-output-stream)
26959     (clear-stream $_test-output-buffered-file->buffer)
26960     # simulate allocated payloads starting with an initial fake alloc-id (0x11)
26961 $test-emit-subx-stmt-primitive:initialize-type:
26962     # var type/ecx: (payload type-tree) = int
26963     68/push 0/imm32/right:null
26964     68/push 0/imm32/right:null
26965     68/push 0/imm32/left:unused
26966     68/push 1/imm32/value:int
26967     68/push 1/imm32/is-atom?:true
26968     68/push 0x11/imm32/alloc-id:fake:payload
26969     89/<- %ecx 4/r32/esp
26970 $test-emit-subx-stmt-primitive:initialize-var:
26971     # var var-foo/ecx: (payload var) = var(type)
26972     68/push 0/imm32/no-register
26973     68/push 0/imm32/no-register
26974     68/push -8/imm32/stack-offset
26975     68/push 1/imm32/block-depth
26976     51/push-ecx/type
26977     68/push 0x11/imm32/alloc-id:fake
26978     68/push 0/imm32/name
26979     68/push 0/imm32/name
26980     68/push 0x11/imm32/alloc-id:fake:payload
26981     89/<- %ecx 4/r32/esp
26982 $test-emit-subx-stmt-primitive:initialize-var-name:
26983     # var-foo->name = "foo"
26984     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
26985     (copy-array Heap "foo" %eax)
26986 $test-emit-subx-stmt-primitive:initialize-stmt-var:
26987     # var operand/ebx: (payload stmt-var) = stmt-var(var-foo)
26988     68/push 0/imm32/is-deref:false
26989     68/push 0/imm32/next
26990     68/push 0/imm32/next
26991     51/push-ecx/var-foo
26992     68/push 0x11/imm32/alloc-id:fake
26993     68/push 0x11/imm32/alloc-id:fake:payload
26994     89/<- %ebx 4/r32/esp
26995 $test-emit-subx-stmt-primitive:initialize-stmt:
26996     # var stmt/esi: (addr statement)
26997     68/push 0/imm32/no-outputs
26998     68/push 0/imm32/no-outputs
26999     53/push-ebx/inouts
27000     68/push 0x11/imm32/alloc-id:fake
27001     68/push 0/imm32/operation
27002     68/push 0/imm32/operation
27003     68/push 1/imm32/tag
27004     89/<- %esi 4/r32/esp
27005 $test-emit-subx-stmt-primitive:initialize-stmt-operation:
27006     # stmt->operation = "increment"
27007     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
27008     (copy-array Heap "increment" %eax)
27009 $test-emit-subx-stmt-primitive:initialize-primitive:
27010     # var primitives/ebx: (addr primitive)
27011     68/push 0/imm32/next
27012     68/push 0/imm32/next
27013     68/push 0/imm32/no-x32
27014     68/push 0/imm32/no-xm32
27015     68/push 0/imm32/no-disp32
27016     68/push 0/imm32/no-imm8
27017     68/push 0/imm32/no-imm32
27018     68/push 0/imm32/no-r32
27019     68/push 1/imm32/rm32-is-first-inout
27020     68/push 0/imm32/subx-name
27021     68/push 0/imm32/subx-name
27022     68/push 0/imm32/no-outputs
27023     68/push 0/imm32/no-outputs
27024     53/push-ebx/inouts  # hack: reuse stmt-var from call stmt as (list var) in function declaration
27025     68/push 0x11/imm32/alloc-id:fake
27026     68/push 0/imm32/name
27027     68/push 0/imm32/name
27028     89/<- %ebx 4/r32/esp
27029 $test-emit-subx-stmt-primitive:initialize-primitive-name:
27030     # primitives->name = "increment"
27031     (copy-array Heap "increment" %ebx)  # Primitive-name
27032 $test-emit-subx-stmt-primitive:initialize-primitive-subx-name:
27033     # primitives->subx-name = "ff 0/subop/increment"
27034     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
27035     (copy-array Heap "ff 0/subop/increment" %eax)
27036     # convert
27037     c7 0/subop/copy *Curr-block-depth 0/imm32
27038     (emit-subx-stmt _test-output-buffered-file %esi %ebx Stderr 0)
27039     (flush _test-output-buffered-file)
27040 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
27046     # check output
27047     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment *(ebp+0xfffffff8)" "F - test-emit-subx-stmt-primitive")
27048     # . epilogue
27049     89/<- %esp 5/r32/ebp
27050     5d/pop-to-ebp
27051     c3/return
27052 
27053 test-emit-subx-stmt-primitive-register:
27054     # Primitive operation on a variable in a register.
27055     #   foo <- increment
27056     # =>
27057     #   ff 0/subop/increment %eax  # sub-optimal, but should suffice
27058     #
27059     # There's a variable on the var stack as follows:
27060     #   name: 'foo'
27061     #   type: int
27062     #   register: 'eax'
27063     #
27064     # There's a primitive with this info:
27065     #   name: 'increment'
27066     #   out: int/reg
27067     #   value: 'ff 0/subop/increment'
27068     #
27069     # . prologue
27070     55/push-ebp
27071     89/<- %ebp 4/r32/esp
27072     # setup
27073     (clear-stream _test-output-stream)
27074     (clear-stream $_test-output-buffered-file->buffer)
27075 $test-emit-subx-stmt-primitive-register:initialize-type:
27076     # var type/ecx: (payload type-tree) = int
27077     68/push 0/imm32/right:null
27078     68/push 0/imm32/right:null
27079     68/push 0/imm32/left:unused
27080     68/push 1/imm32/value:int
27081     68/push 1/imm32/is-atom?:true
27082     68/push 0x11/imm32/alloc-id:fake:payload
27083     89/<- %ecx 4/r32/esp
27084 $test-emit-subx-stmt-primitive-register:initialize-var:
27085     # var var-foo/ecx: (payload var)
27086     68/push 0/imm32/register
27087     68/push 0/imm32/register
27088     68/push 0/imm32/no-stack-offset
27089     68/push 1/imm32/block-depth
27090     51/push-ecx
27091     68/push 0x11/imm32/alloc-id:fake
27092     68/push 0/imm32/name
27093     68/push 0/imm32/name
27094     68/push 0x11/imm32/alloc-id:fake:payload
27095     89/<- %ecx 4/r32/esp
27096 $test-emit-subx-stmt-primitive-register:initialize-var-name:
27097     # var-foo->name = "foo"
27098     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
27099     (copy-array Heap "foo" %eax)
27100 $test-emit-subx-stmt-primitive-register:initialize-var-register:
27101     # var-foo->register = "eax"
27102     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
27103     (copy-array Heap "eax" %eax)
27104 $test-emit-subx-stmt-primitive-register:initialize-stmt-var:
27105     # var operand/ebx: (payload stmt-var)
27106     68/push 0/imm32/is-deref:false
27107     68/push 0/imm32/next
27108     68/push 0/imm32/next
27109     51/push-ecx/var-foo
27110     68/push 0x11/imm32/alloc-id:fake
27111     68/push 0x11/imm32/alloc-id:fake:payload
27112     89/<- %ebx 4/r32/esp
27113 $test-emit-subx-stmt-primitive-register:initialize-stmt:
27114     # var stmt/esi: (addr statement)
27115     53/push-ebx/outputs
27116     68/push 0x11/imm32/alloc-id:fake
27117     68/push 0/imm32/no-inouts
27118     68/push 0/imm32/no-inouts
27119     68/push 0/imm32/operation
27120     68/push 0/imm32/operation
27121     68/push 1/imm32
27122     89/<- %esi 4/r32/esp
27123 $test-emit-subx-stmt-primitive-register:initialize-stmt-operation:
27124     # stmt->operation = "increment"
27125     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
27126     (copy-array Heap "increment" %eax)
27127 $test-emit-subx-stmt-primitive-register:initialize-formal-var:
27128     # var formal-var/ebx: (payload var)
27129     68/push 0/imm32/register
27130     68/push 0/imm32/register
27131     68/push 0/imm32/no-stack-offset
27132     68/push 1/imm32/block-depth
27133     ff 6/subop/push *(ecx+0x10)  # Var-type + payload alloc id + handle alloc id
27134     68/push 0x11/imm32/alloc-id:fake
27135     68/push 0/imm32/name
27136     68/push 0/imm32/name
27137     68/push 0x11/imm32/alloc-id:fake:payload
27138     89/<- %ebx 4/r32/esp
27139 $test-emit-subx-stmt-primitive-register:initialize-formal-var-name:
27140     # formal-var->name = "dummy"
27141     8d/copy-address *(ebx+4) 0/r32/eax  # Var-name + 4
27142     (copy-array Heap "dummy" %eax)
27143 $test-emit-subx-stmt-primitive-register:initialize-formal-register:
27144     # formal-var->register = "*"
27145     8d/copy-address *(ebx+0x1c) 0/r32/eax  # Var-register + 4
27146     (copy-array Heap "*" %eax)  # Any-register
27147 $test-emit-subx-stmt-primitive-register:initialize-var-list:
27148     # var formal-outputs/ebx: (payload list var)
27149     68/push 0/imm32/next
27150     68/push 0/imm32/next
27151     53/push-ebx/formal-var
27152     68/push 0x11/imm32/alloc-id:fake
27153     68/push 0x11/imm32/alloc-id:fake:payload
27154     89/<- %ebx 4/r32/esp
27155 $test-emit-subx-stmt-primitive-register:initialize-primitive:
27156     # var primitives/ebx: (addr primitive)
27157     68/push 0/imm32/next
27158     68/push 0/imm32/next
27159     68/push 0/imm32/no-x32
27160     68/push 0/imm32/no-xm32
27161     68/push 0/imm32/no-disp32
27162     68/push 0/imm32/no-imm8
27163     68/push 0/imm32/no-imm32
27164     68/push 0/imm32/no-r32
27165     68/push 3/imm32/rm32-is-first-output
27166     68/push 0/imm32/subx-name
27167     68/push 0/imm32/subx-name
27168     53/push-ebx/outputs
27169     68/push 0x11/imm32/alloc-id:fake
27170     68/push 0/imm32/no-inouts
27171     68/push 0/imm32/no-inouts
27172     68/push 0/imm32/name
27173     68/push 0/imm32/name
27174     89/<- %ebx 4/r32/esp
27175 $test-emit-subx-stmt-primitive-register:initialize-primitive-name:
27176     # primitives->name = "increment"
27177     (copy-array Heap "increment" %ebx)  # Primitive-name
27178 $test-emit-subx-stmt-primitive-register:initialize-primitive-subx-name:
27179     # primitives->subx-name = "ff 0/subop/increment"
27180     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
27181     (copy-array Heap "ff 0/subop/increment" %eax)
27182     # convert
27183     c7 0/subop/copy *Curr-block-depth 0/imm32
27184     (emit-subx-stmt _test-output-buffered-file %esi %ebx Stderr 0)
27185     (flush _test-output-buffered-file)
27186 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
27192     # check output
27193     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-primitive-register")
27194     # . epilogue
27195     89/<- %esp 5/r32/ebp
27196     5d/pop-to-ebp
27197     c3/return
27198 
27199 test-emit-subx-stmt-select-primitive:
27200     # Select the right primitive between overloads.
27201     #   foo <- increment
27202     # =>
27203     #   ff 0/subop/increment %eax  # sub-optimal, but should suffice
27204     #
27205     # There's a variable on the var stack as follows:
27206     #   name: 'foo'
27207     #   type: int
27208     #   register: 'eax'
27209     #
27210     # There's two primitives, as follows:
27211     #   - name: 'increment'
27212     #     out: int/reg
27213     #     value: 'ff 0/subop/increment'
27214     #   - name: 'increment'
27215     #     inout: int/mem
27216     #     value: 'ff 0/subop/increment'
27217     #
27218     # . prologue
27219     55/push-ebp
27220     89/<- %ebp 4/r32/esp
27221     # setup
27222     (clear-stream _test-output-stream)
27223     (clear-stream $_test-output-buffered-file->buffer)
27224 $test-emit-subx-stmt-select-primitive:initialize-type:
27225     # var type/ecx: (payload type-tree) = int
27226     68/push 0/imm32/right:null
27227     68/push 0/imm32/right:null
27228     68/push 0/imm32/left:unused
27229     68/push 1/imm32/value:int
27230     68/push 1/imm32/is-atom?:true
27231     68/push 0x11/imm32/alloc-id:fake:payload
27232     89/<- %ecx 4/r32/esp
27233 $test-emit-subx-stmt-select-primitive:initialize-var:
27234     # var var-foo/ecx: (payload var)
27235     68/push 0/imm32/register
27236     68/push 0/imm32/register
27237     68/push 0/imm32/no-stack-offset
27238     68/push 1/imm32/block-depth
27239     51/push-ecx
27240     68/push 0x11/imm32/alloc-id:fake
27241     68/push 0/imm32/name
27242     68/push 0/imm32/name
27243     68/push 0x11/imm32/alloc-id:fake:payload
27244     89/<- %ecx 4/r32/esp
27245 $test-emit-subx-stmt-select-primitive:initialize-var-name:
27246     # var-foo->name = "foo"
27247     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
27248     (copy-array Heap "foo" %eax)
27249 $test-emit-subx-stmt-select-primitive:initialize-var-register:
27250     # var-foo->register = "eax"
27251     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
27252     (copy-array Heap "eax" %eax)
27253 $test-emit-subx-stmt-select-primitive:initialize-stmt-var:
27254     # var operand/ebx: (payload stmt-var)
27255     68/push 0/imm32/is-deref:false
27256     68/push 0/imm32/next
27257     68/push 0/imm32/next
27258     51/push-ecx/var-foo
27259     68/push 0x11/imm32/alloc-id:fake
27260     68/push 0x11/imm32/alloc-id:fake:payload
27261     89/<- %ebx 4/r32/esp
27262 $test-emit-subx-stmt-select-primitive:initialize-stmt:
27263     # var stmt/esi: (addr statement)
27264     53/push-ebx/outputs
27265     68/push 0x11/imm32/alloc-id:fake
27266     68/push 0/imm32/no-inouts
27267     68/push 0/imm32/no-inouts
27268     68/push 0/imm32/operation
27269     68/push 0/imm32/operation
27270     68/push 1/imm32
27271     89/<- %esi 4/r32/esp
27272 $test-emit-subx-stmt-select-primitive:initialize-stmt-operation:
27273     # stmt->operation = "increment"
27274     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
27275     (copy-array Heap "increment" %eax)
27276 $test-emit-subx-stmt-select-primitive:initialize-formal-var:
27277     # var formal-var/ebx: (payload var)
27278     68/push 0/imm32/register
27279     68/push 0/imm32/register
27280     68/push 0/imm32/no-stack-offset
27281     68/push 1/imm32/block-depth
27282     ff 6/subop/push *(ecx+0x10)  # Var-type + payload alloc id + handle alloc id
27283     68/push 0x11/imm32/alloc-id:fake
27284     68/push 0/imm32/name
27285     68/push 0/imm32/name
27286     68/push 0x11/imm32/alloc-id:fake:payload
27287     89/<- %ebx 4/r32/esp
27288 $test-emit-subx-stmt-select-primitive:initialize-formal-var-name:
27289     # formal-var->name = "dummy"
27290     8d/copy-address *(ebx+4) 0/r32/eax  # Var-name + 4
27291     (copy-array Heap "dummy" %eax)
27292 $test-emit-subx-stmt-select-primitive:initialize-formal-register:
27293     # formal-var->register = "*"
27294     8d/copy-address *(ebx+0x1c) 0/r32/eax  # Var-register + 4
27295     (copy-array Heap "*" %eax)  # Any-register
27296 $test-emit-subx-stmt-select-primitive:initialize-var-list:
27297     # var formal-outputs/ebx: (payload list var)
27298     68/push 0/imm32/next
27299     68/push 0/imm32/next
27300     53/push-ebx/formal-var
27301     68/push 0x11/imm32/alloc-id:fake
27302     68/push 0x11/imm32/alloc-id:fake:payload
27303     89/<- %ebx 4/r32/esp
27304 $test-emit-subx-stmt-select-primitive:initialize-primitive2:
27305     # var primitive2/edi: (payload primitive)
27306     68/push 0/imm32/next
27307     68/push 0/imm32/next
27308     68/push 0/imm32/no-x32
27309     68/push 0/imm32/no-xm32
27310     68/push 0/imm32/no-disp32
27311     68/push 0/imm32/no-imm8
27312     68/push 0/imm32/no-imm32
27313     68/push 0/imm32/no-r32
27314     68/push 3/imm32/rm32-is-first-output
27315     68/push 0/imm32/subx-name
27316     68/push 0/imm32/subx-name
27317     53/push-ebx/outputs
27318     68/push 0x11/imm32/alloc-id:fake
27319     68/push 0/imm32/no-inouts
27320     68/push 0/imm32/no-inouts
27321     68/push 0/imm32/name
27322     68/push 0/imm32/name
27323     68/push 0x11/imm32/alloc-id:fake:payload
27324     89/<- %edi 4/r32/esp
27325 $test-emit-subx-stmt-select-primitive:initialize-primitive2-name:
27326     # primitives->name = "increment"
27327     8d/copy-address *(edi+4) 0/r32/eax  # Primitive-name + 4
27328     (copy-array Heap "increment" %eax)
27329 $test-emit-subx-stmt-select-primitive:initialize-primitive2-subx-name:
27330     # primitives->subx-name = "ff 0/subop/increment"
27331     8d/copy-address *(edi+0x1c) 0/r32/eax  # Primitive-subx-name + 4
27332     (copy-array Heap "ff 0/subop/increment" %eax)
27333 $test-emit-subx-stmt-select-primitive:initialize-primitive:
27334     # var primitives/ebx: (addr primitive)
27335     57/push-edi
27336     68/push 0x11/imm32/alloc-id:fake
27337     68/push 0/imm32/no-x32
27338     68/push 0/imm32/no-xm32
27339     68/push 0/imm32/no-disp32
27340     68/push 0/imm32/no-imm8
27341     68/push 0/imm32/no-imm32
27342     68/push 0/imm32/no-r32
27343     68/push 1/imm32/rm32-is-first-inout
27344     68/push 0/imm32/subx-name
27345     68/push 0/imm32/subx-name
27346     68/push 0/imm32/no-outputs
27347     68/push 0/imm32/no-outputs
27348     53/push-ebx/inouts  # hack: reuse stmt-var from call stmt as (list var) in function declaration
27349     68/push 0x11/imm32/alloc-id:fake
27350     68/push 0/imm32/name
27351     68/push 0/imm32/name
27352     89/<- %ebx 4/r32/esp
27353 $test-emit-subx-stmt-select-primitive:initialize-primitive-name:
27354     # primitives->name = "increment"
27355     (copy-array Heap "increment" %ebx)  # Primitive-name
27356 $test-emit-subx-stmt-select-primitive:initialize-primitive-subx-name:
27357     # primitives->subx-name = "ff 0/subop/increment"
27358     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
27359     (copy-array Heap "ff 0/subop/increment" %eax)
27360     # convert
27361     c7 0/subop/copy *Curr-block-depth 0/imm32
27362     (emit-subx-stmt _test-output-buffered-file %esi %ebx Stderr 0)
27363     (flush _test-output-buffered-file)
27364 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
27370     # check output
27371     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-select-primitive")
27372     # . epilogue
27373     89/<- %esp 5/r32/ebp
27374     5d/pop-to-ebp
27375     c3/return
27376 
27377 test-emit-subx-stmt-select-primitive-2:
27378     # Select the right primitive between overloads.
27379     #   increment foo
27380     # =>
27381     #   ff 0/subop/increment %eax  # sub-optimal, but should suffice
27382     #
27383     # There's a variable on the var stack as follows:
27384     #   name: 'foo'
27385     #   type: int
27386     #   register: 'eax'
27387     #
27388     # There's two primitives, as follows:
27389     #   - name: 'increment'
27390     #     out: int/reg
27391     #     value: 'ff 0/subop/increment'
27392     #   - name: 'increment'
27393     #     inout: int/mem
27394     #     value: 'ff 0/subop/increment'
27395     #
27396     # . prologue
27397     55/push-ebp
27398     89/<- %ebp 4/r32/esp
27399     # setup
27400     (clear-stream _test-output-stream)
27401     (clear-stream $_test-output-buffered-file->buffer)
27402 $test-emit-subx-stmt-select-primitive-2:initialize-type:
27403     # var type/ecx: (payload type-tree) = int
27404     68/push 0/imm32/right:null
27405     68/push 0/imm32/right:null
27406     68/push 0/imm32/left:unused
27407     68/push 1/imm32/value:int
27408     68/push 1/imm32/is-atom?:true
27409     68/push 0x11/imm32/alloc-id:fake:payload
27410     89/<- %ecx 4/r32/esp
27411 $test-emit-subx-stmt-select-primitive-2:initialize-var:
27412     # var var-foo/ecx: (payload var)
27413     68/push 0/imm32/register
27414     68/push 0/imm32/register
27415     68/push 0/imm32/no-stack-offset
27416     68/push 1/imm32/block-depth
27417     51/push-ecx
27418     68/push 0x11/imm32/alloc-id:fake
27419     68/push 0/imm32/name
27420     68/push 0/imm32/name
27421     68/push 0x11/imm32/alloc-id:fake:payload
27422     89/<- %ecx 4/r32/esp
27423 $test-emit-subx-stmt-select-primitive-2:initialize-var-name:
27424     # var-foo->name = "foo"
27425     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
27426     (copy-array Heap "foo" %eax)
27427 $test-emit-subx-stmt-select-primitive-2:initialize-var-register:
27428     # var-foo->register = "eax"
27429     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
27430     (copy-array Heap "eax" %eax)
27431 $test-emit-subx-stmt-select-primitive-2:initialize-stmt-var:
27432     # var operand/ebx: (payload stmt-var)
27433     68/push 0/imm32/is-deref:false
27434     68/push 0/imm32/next
27435     68/push 0/imm32/next
27436     51/push-ecx/var-foo
27437     68/push 0x11/imm32/alloc-id:fake
27438     68/push 0x11/imm32/alloc-id:fake:payload
27439     89/<- %ebx 4/r32/esp
27440 $test-emit-subx-stmt-select-primitive-2:initialize-stmt:
27441     # var stmt/esi: (addr statement)
27442     68/push 0/imm32/no-outputs
27443     68/push 0/imm32/no-outputs
27444     53/push-ebx/inouts
27445     68/push 0x11/imm32/alloc-id:fake
27446     68/push 0/imm32/operation
27447     68/push 0/imm32/operation
27448     68/push 1/imm32
27449     89/<- %esi 4/r32/esp
27450 $test-emit-subx-stmt-select-primitive-2:initialize-stmt-operation:
27451     # stmt->operation = "increment"
27452     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
27453     (copy-array Heap "increment" %eax)
27454 $test-emit-subx-stmt-select-primitive-2:initialize-formal-var:
27455     # var formal-var/ebx: (payload var)
27456     68/push 0/imm32/register
27457     68/push 0/imm32/register
27458     68/push 0/imm32/no-stack-offset
27459     68/push 1/imm32/block-depth
27460     ff 6/subop/push *(ecx+0x10)  # Var-type + payload alloc id + handle alloc id
27461     68/push 0x11/imm32/alloc-id:fake
27462     68/push 0/imm32/name
27463     68/push 0/imm32/name
27464     68/push 0x11/imm32/alloc-id:fake:payload
27465     89/<- %ebx 4/r32/esp
27466 $test-emit-subx-stmt-select-primitive-2:initialize-formal-var-name:
27467     # formal-var->name = "dummy"
27468     8d/copy-address *(ebx+4) 0/r32/eax  # Var-name + 4
27469     (copy-array Heap "dummy" %eax)
27470 $test-emit-subx-stmt-select-primitive-2:initialize-formal-register:
27471     # formal-var->register = "*"
27472     8d/copy-address *(ebx+0x1c) 0/r32/eax  # Var-register + 4
27473     (copy-array Heap "*" %eax)  # Any-register
27474 $test-emit-subx-stmt-select-primitive-2:initialize-var-list:
27475     # var formal-outputs/ebx: (payload list stmt-var)
27476     68/push 0/imm32/next
27477     68/push 0/imm32/next
27478     53/push-ebx/formal-var
27479     68/push 0x11/imm32/alloc-id:fake
27480     68/push 0x11/imm32/alloc-id:fake:payload
27481     89/<- %ebx 4/r32/esp
27482 $test-emit-subx-stmt-select-primitive-2:initialize-primitive2:
27483     # var primitive2/edi: (payload primitive)
27484     68/push 0/imm32/next
27485     68/push 0/imm32/next
27486     68/push 0/imm32/no-x32
27487     68/push 0/imm32/no-xm32
27488     68/push 0/imm32/no-disp32
27489     68/push 0/imm32/no-imm8
27490     68/push 0/imm32/no-imm32
27491     68/push 0/imm32/no-r32
27492     68/push 3/imm32/rm32-is-first-output
27493     68/push 0/imm32/subx-name
27494     68/push 0/imm32/subx-name
27495     53/push-ebx/outputs
27496     68/push 0x11/imm32/alloc-id:fake
27497     68/push 0/imm32/no-inouts
27498     68/push 0/imm32/no-inouts
27499     68/push 0/imm32/name
27500     68/push 0/imm32/name
27501     68/push 0x11/imm32/alloc-id:fake:payload
27502     89/<- %edi 4/r32/esp
27503 $test-emit-subx-stmt-select-primitive-2:initialize-primitive2-name:
27504     # primitives->name = "increment"
27505     8d/copy-address *(edi+4) 0/r32/eax  # Primitive-name + 4
27506     (copy-array Heap "increment" %eax)
27507 $test-emit-subx-stmt-select-primitive-2:initialize-primitive2-subx-name:
27508     # primitives->subx-name = "ff 0/subop/increment"
27509     8d/copy-address *(edi+0x1c) 0/r32/eax  # Primitive-subx-name + 4
27510     (copy-array Heap "ff 0/subop/increment" %eax)
27511 $test-emit-subx-stmt-select-primitive-2:initialize-primitive:
27512     # var primitives/ebx: (addr primitive)
27513     57/push-edi
27514     68/push 0x11/imm32/alloc-id:fake
27515     68/push 0/imm32/no-x32
27516     68/push 0/imm32/no-xm32
27517     68/push 0/imm32/no-disp32
27518     68/push 0/imm32/no-imm8
27519     68/push 0/imm32/no-imm32
27520     68/push 0/imm32/no-r32
27521     68/push 1/imm32/rm32-is-first-inout
27522     68/push 0/imm32/subx-name
27523     68/push 0/imm32/subx-name
27524     68/push 0/imm32/no-outputs
27525     68/push 0/imm32/no-outputs
27526     53/push-ebx/inouts  # hack: reuse stmt-var from call stmt as (list var) in function declaration
27527     68/push 0x11/imm32/alloc-id:fake
27528     68/push 0/imm32/name
27529     68/push 0/imm32/name
27530     89/<- %ebx 4/r32/esp
27531 $test-emit-subx-stmt-select-primitive-2:initialize-primitive-name:
27532     # primitives->name = "increment"
27533     (copy-array Heap "increment" %ebx)  # Primitive-name
27534 $test-emit-subx-stmt-select-primitive-2:initialize-primitive-subx-name:
27535     # primitives->subx-name = "ff 0/subop/increment"
27536     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
27537     (copy-array Heap "ff 0/subop/increment" %eax)
27538     # convert
27539     c7 0/subop/copy *Curr-block-depth 0/imm32
27540     (emit-subx-stmt _test-output-buffered-file %esi %ebx Stderr 0)
27541     (flush _test-output-buffered-file)
27542 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
27548     # check output
27549     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-select-primitive-2")
27550     # . epilogue
27551     89/<- %esp 5/r32/ebp
27552     5d/pop-to-ebp
27553     c3/return
27554 
27555 test-increment-register:
27556     # Select the right register between overloads.
27557     #   foo <- increment
27558     # =>
27559     #   50/increment-eax
27560     #
27561     # There's a variable on the var stack as follows:
27562     #   name: 'foo'
27563     #   type: int
27564     #   register: 'eax'
27565     #
27566     # Primitives are the global definitions.
27567     #
27568     # . prologue
27569     55/push-ebp
27570     89/<- %ebp 4/r32/esp
27571     # setup
27572     (clear-stream _test-output-stream)
27573     (clear-stream $_test-output-buffered-file->buffer)
27574 $test-increment-register:initialize-type:
27575     # var type/ecx: (payload type-tree) = int
27576     68/push 0/imm32/right:null
27577     68/push 0/imm32/right:null
27578     68/push 0/imm32/left:unused
27579     68/push 1/imm32/value:int
27580     68/push 1/imm32/is-atom?:true
27581     68/push 0x11/imm32/alloc-id:fake:payload
27582     89/<- %ecx 4/r32/esp
27583 $test-increment-register:initialize-var:
27584     # var var-foo/ecx: (payload var)
27585     68/push 0/imm32/register
27586     68/push 0/imm32/register
27587     68/push 0/imm32/no-stack-offset
27588     68/push 1/imm32/block-depth
27589     51/push-ecx
27590     68/push 0x11/imm32/alloc-id:fake
27591     68/push 0/imm32/name
27592     68/push 0/imm32/name
27593     68/push 0x11/imm32/alloc-id:fake:payload
27594     89/<- %ecx 4/r32/esp
27595 $test-increment-register:initialize-var-name:
27596     # var-foo->name = "foo"
27597     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
27598     (copy-array Heap "foo" %eax)
27599 $test-increment-register:initialize-var-register:
27600     # var-foo->register = "eax"
27601     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
27602     (copy-array Heap "eax" %eax)
27603 $test-increment-register:initialize-stmt-var:
27604     # var operand/ebx: (payload stmt-var)
27605     68/push 0/imm32/is-deref:false
27606     68/push 0/imm32/next
27607     68/push 0/imm32/next
27608     51/push-ecx/var-foo
27609     68/push 0x11/imm32/alloc-id:fake
27610     68/push 0x11/imm32/alloc-id:fake:payload
27611     89/<- %ebx 4/r32/esp
27612 $test-increment-register:initialize-stmt:
27613     # var stmt/esi: (addr statement)
27614     53/push-ebx/outputs
27615     68/push 0x11/imm32/alloc-id:fake
27616     68/push 0/imm32/no-inouts
27617     68/push 0/imm32/no-inouts
27618     68/push 0/imm32/operation
27619     68/push 0/imm32/operation
27620     68/push 1/imm32
27621     89/<- %esi 4/r32/esp
27622 $test-increment-register:initialize-stmt-operation:
27623     # stmt->operation = "increment"
27624     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
27625     (copy-array Heap "increment" %eax)
27626     # convert
27627     c7 0/subop/copy *Curr-block-depth 0/imm32
27628     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
27629     (flush _test-output-buffered-file)
27630 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
27636     # check output
27637     (check-next-stream-line-equal _test-output-stream "40/increment-eax" "F - test-increment-register")
27638     # . epilogue
27639     89/<- %esp 5/r32/ebp
27640     5d/pop-to-ebp
27641     c3/return
27642 
27643 test-add-reg-to-reg:
27644     #   var1/reg <- add var2/reg
27645     # =>
27646     #   01/add-to %var1 var2
27647     #
27648     # . prologue
27649     55/push-ebp
27650     89/<- %ebp 4/r32/esp
27651     # setup
27652     (clear-stream _test-output-stream)
27653     (clear-stream $_test-output-buffered-file->buffer)
27654 $test-add-reg-to-reg:initialize-type:
27655     # var type/ecx: (payload type-tree) = int
27656     68/push 0/imm32/right:null
27657     68/push 0/imm32/right:null
27658     68/push 0/imm32/left:unused
27659     68/push 1/imm32/value:int
27660     68/push 1/imm32/is-atom?:true
27661     68/push 0x11/imm32/alloc-id:fake:payload
27662     89/<- %ecx 4/r32/esp
27663 $test-add-reg-to-reg:initialize-var1:
27664     # var var1/ecx: (payload var)
27665     68/push 0/imm32/register
27666     68/push 0/imm32/register
27667     68/push 0/imm32/no-stack-offset
27668     68/push 1/imm32/block-depth
27669     51/push-ecx
27670     68/push 0x11/imm32/alloc-id:fake
27671     68/push 0/imm32/name
27672     68/push 0/imm32/name
27673     68/push 0x11/imm32/alloc-id:fake:payload
27674     89/<- %ecx 4/r32/esp
27675 $test-add-reg-to-reg:initialize-var1-name:
27676     # var1->name = "var1"
27677     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
27678     (copy-array Heap "var1" %eax)
27679 $test-add-reg-to-reg:initialize-var1-register:
27680     # var1->register = "eax"
27681     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
27682     (copy-array Heap "eax" %eax)
27683 $test-add-reg-to-reg:initialize-var2:
27684     # var var2/edx: (payload var)
27685     68/push 0/imm32/register
27686     68/push 0/imm32/register
27687     68/push 0/imm32/no-stack-offset
27688     68/push 1/imm32/block-depth
27689     ff 6/subop/push *(ecx+0x10)
27690     68/push 0x11/imm32/alloc-id:fake
27691     68/push 0/imm32/name
27692     68/push 0/imm32/name
27693     68/push 0x11/imm32/alloc-id:fake:payload
27694     89/<- %edx 4/r32/esp
27695 $test-add-reg-to-reg:initialize-var2-name:
27696     # var2->name = "var2"
27697     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
27698     (copy-array Heap "var2" %eax)
27699 $test-add-reg-to-reg:initialize-var2-register:
27700     # var2->register = "ecx"
27701     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
27702     (copy-array Heap "ecx" %eax)
27703 $test-add-reg-to-reg:initialize-inouts:
27704     # var inouts/esi: (payload stmt-var) = [var2]
27705     68/push 0/imm32/is-deref:false
27706     68/push 0/imm32/next
27707     68/push 0/imm32/next
27708     52/push-edx/var2
27709     68/push 0x11/imm32/alloc-id:fake
27710     68/push 0x11/imm32/alloc-id:fake:payload
27711     89/<- %esi 4/r32/esp
27712 $test-add-reg-to-reg:initialize-outputs:
27713     # var outputs/edi: (payload stmt-var) = [var1]
27714     68/push 0/imm32/is-deref:false
27715     68/push 0/imm32/next
27716     68/push 0/imm32/next
27717     51/push-ecx/var1
27718     68/push 0x11/imm32/alloc-id:fake
27719     68/push 0x11/imm32/alloc-id:fake:payload
27720     89/<- %edi 4/r32/esp
27721 $test-add-reg-to-reg:initialize-stmt:
27722     # var stmt/esi: (addr statement)
27723     68/push 0/imm32/next
27724     68/push 0/imm32/next
27725     57/push-edi/outputs
27726     68/push 0x11/imm32/alloc-id:fake
27727     56/push-esi/inouts
27728     68/push 0x11/imm32/alloc-id:fake
27729     68/push 0/imm32/operation
27730     68/push 0/imm32/operation
27731     68/push 1/imm32/tag:stmt1
27732     89/<- %esi 4/r32/esp
27733 $test-add-reg-to-reg:initialize-stmt-operation:
27734     # stmt->operation = "add"
27735     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
27736     (copy-array Heap "add" %eax)
27737     # convert
27738     c7 0/subop/copy *Curr-block-depth 0/imm32
27739     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
27740     (flush _test-output-buffered-file)
27741 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
27747     # check output
27748     (check-next-stream-line-equal _test-output-stream "01/add-to %eax 0x00000001/r32" "F - test-add-reg-to-reg")
27749     # . epilogue
27750     89/<- %esp 5/r32/ebp
27751     5d/pop-to-ebp
27752     c3/return
27753 
27754 test-add-reg-to-mem:
27755     #   add-to var1 var2/reg
27756     # =>
27757     #   01/add-to *(ebp+__) var2
27758     #
27759     # . prologue
27760     55/push-ebp
27761     89/<- %ebp 4/r32/esp
27762     # setup
27763     (clear-stream _test-output-stream)
27764     (clear-stream $_test-output-buffered-file->buffer)
27765 $test-add-reg-to-mem:initialize-type:
27766     # var type/ecx: (payload type-tree) = int
27767     68/push 0/imm32/right:null
27768     68/push 0/imm32/right:null
27769     68/push 0/imm32/left:unused
27770     68/push 1/imm32/value:int
27771     68/push 1/imm32/is-atom?:true
27772     68/push 0x11/imm32/alloc-id:fake:payload
27773     89/<- %ecx 4/r32/esp
27774 $test-add-reg-to-mem:initialize-var1:
27775     # var var1/ecx: (payload var)
27776     68/push 0/imm32/register
27777     68/push 0/imm32/register
27778     68/push 8/imm32/stack-offset
27779     68/push 1/imm32/block-depth
27780     51/push-ecx
27781     68/push 0x11/imm32/alloc-id:fake
27782     68/push 0/imm32/name
27783     68/push 0/imm32/name
27784     68/push 0x11/imm32/alloc-id:fake:payload
27785     89/<- %ecx 4/r32/esp
27786 $test-add-reg-to-mem:initialize-var1-name:
27787     # var1->name = "var1"
27788     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
27789     (copy-array Heap "var1" %eax)
27790 $test-add-reg-to-mem:initialize-var2:
27791     # var var2/edx: (payload var)
27792     68/push 0/imm32/register
27793     68/push 0/imm32/register
27794     68/push 0/imm32/no-stack-offset
27795     68/push 1/imm32/block-depth
27796     ff 6/subop/push *(ecx+0x10)
27797     68/push 0x11/imm32/alloc-id:fake
27798     68/push 0/imm32/name
27799     68/push 0/imm32/name
27800     68/push 0x11/imm32/alloc-id:fake:payload
27801     89/<- %edx 4/r32/esp
27802 $test-add-reg-to-mem:initialize-var2-name:
27803     # var2->name = "var2"
27804     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
27805     (copy-array Heap "var2" %eax)
27806 $test-add-reg-to-mem:initialize-var2-register:
27807     # var2->register = "ecx"
27808     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
27809     (copy-array Heap "ecx" %eax)
27810 $test-add-reg-to-mem:initialize-inouts:
27811     # var inouts/esi: (payload stmt-var) = [var2]
27812     68/push 0/imm32/is-deref:false
27813     68/push 0/imm32/next
27814     68/push 0/imm32/next
27815     52/push-edx/var2
27816     68/push 0x11/imm32/alloc-id:fake
27817     68/push 0x11/imm32/alloc-id:fake:payload
27818     89/<- %esi 4/r32/esp
27819     # inouts = [var1, var2]
27820     68/push 0/imm32/is-deref:false
27821     56/push-esi/next
27822     68/push 0x11/imm32/alloc-id:fake
27823     51/push-ecx/var1
27824     68/push 0x11/imm32/alloc-id:fake
27825     68/push 0x11/imm32/alloc-id:fake:payload
27826     89/<- %esi 4/r32/esp
27827 $test-add-reg-to-mem:initialize-stmt:
27828     # var stmt/esi: (addr statement)
27829     68/push 0/imm32/next
27830     68/push 0/imm32/next
27831     68/push 0/imm32/outputs
27832     68/push 0/imm32/outputs
27833     56/push-esi/inouts
27834     68/push 0x11/imm32/alloc-id:fake
27835     68/push 0/imm32/operation
27836     68/push 0/imm32/operation
27837     68/push 1/imm32/tag:stmt1
27838     89/<- %esi 4/r32/esp
27839 $test-add-reg-to-mem:initialize-stmt-operation:
27840     # stmt->operation = "add-to"
27841     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
27842     (copy-array Heap "add-to" %eax)
27843     # convert
27844     c7 0/subop/copy *Curr-block-depth 0/imm32
27845     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
27846     (flush _test-output-buffered-file)
27847 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
27853     # check output
27854     (check-next-stream-line-equal _test-output-stream "01/add-to *(ebp+0x00000008) 0x00000001/r32" "F - test-add-reg-to-mem")
27855     # . epilogue
27856     89/<- %esp 5/r32/ebp
27857     5d/pop-to-ebp
27858     c3/return
27859 
27860 test-add-mem-to-reg:
27861     #   var1/reg <- add var2
27862     # =>
27863     #   03/add *(ebp+__) var1
27864     #
27865     # . prologue
27866     55/push-ebp
27867     89/<- %ebp 4/r32/esp
27868     # setup
27869     (clear-stream _test-output-stream)
27870     (clear-stream $_test-output-buffered-file->buffer)
27871 $test-add-mem-to-reg:initialize-type:
27872     # var type/ecx: (payload type-tree) = int
27873     68/push 0/imm32/right:null
27874     68/push 0/imm32/right:null
27875     68/push 0/imm32/left:unused
27876     68/push 1/imm32/value:int
27877     68/push 1/imm32/is-atom?:true
27878     68/push 0x11/imm32/alloc-id:fake:payload
27879     89/<- %ecx 4/r32/esp
27880 $test-add-mem-to-reg:initialize-var:
27881     # var var1/ecx: (payload var)
27882     68/push 0/imm32/register
27883     68/push 0/imm32/register
27884     68/push 0/imm32/no-stack-offset
27885     68/push 1/imm32/block-depth
27886     51/push-ecx
27887     68/push 0x11/imm32/alloc-id:fake
27888     68/push 0/imm32/name
27889     68/push 0/imm32/name
27890     68/push 0x11/imm32/alloc-id:fake:payload
27891     89/<- %ecx 4/r32/esp
27892 $test-add-mem-to-reg:initialize-var-name:
27893     # var1->name = "foo"
27894     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
27895     (copy-array Heap "var1" %eax)
27896 $test-add-mem-to-reg:initialize-var-register:
27897     # var1->register = "eax"
27898     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
27899     (copy-array Heap "eax" %eax)
27900 $test-add-mem-to-reg:initialize-var2:
27901     # var var2/edx: (payload var)
27902     68/push 0/imm32/register
27903     68/push 0/imm32/register
27904     68/push 8/imm32/stack-offset
27905     68/push 1/imm32/block-depth
27906     ff 6/subop/push *(ecx+0x10)
27907     68/push 0x11/imm32/alloc-id:fake
27908     68/push 0/imm32/name
27909     68/push 0/imm32/name
27910     68/push 0x11/imm32/alloc-id:fake:payload
27911     89/<- %edx 4/r32/esp
27912 $test-add-mem-to-reg:initialize-var2-name:
27913     # var2->name = "var2"
27914     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
27915     (copy-array Heap "var2" %eax)
27916 $test-add-mem-to-reg:initialize-inouts:
27917     # var inouts/esi: (payload stmt-var) = [var2]
27918     68/push 0/imm32/is-deref:false
27919     68/push 0/imm32/next
27920     68/push 0/imm32/next
27921     52/push-edx/var2
27922     68/push 0x11/imm32/alloc-id:fake
27923     68/push 0x11/imm32/alloc-id:fake:payload
27924     89/<- %esi 4/r32/esp
27925 $test-add-mem-to-reg:initialize-outputs:
27926     # var outputs/edi: (payload stmt-var) = [var1]
27927     68/push 0/imm32/is-deref:false
27928     68/push 0/imm32/next
27929     68/push 0/imm32/next
27930     51/push-ecx/var1
27931     68/push 0x11/imm32/alloc-id:fake
27932     68/push 0x11/imm32/alloc-id:fake:payload
27933     89/<- %edi 4/r32/esp
27934 $test-add-mem-to-reg:initialize-stmt:
27935     # var stmt/esi: (addr statement)
27936     68/push 0/imm32/next
27937     68/push 0/imm32/next
27938     57/push-edi/outputs
27939     68/push 0x11/imm32/alloc-id:fake
27940     56/push-esi/inouts
27941     68/push 0x11/imm32/alloc-id:fake
27942     68/push 0/imm32/operation
27943     68/push 0/imm32/operation
27944     68/push 1/imm32/tag:stmt1
27945     89/<- %esi 4/r32/esp
27946 $test-add-mem-to-reg:initialize-stmt-operation:
27947     # stmt->operation = "add"
27948     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
27949     (copy-array Heap "add" %eax)
27950     # convert
27951     c7 0/subop/copy *Curr-block-depth 0/imm32
27952     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
27953     (flush _test-output-buffered-file)
27954 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
27960     # check output
27961     (check-next-stream-line-equal _test-output-stream "03/add *(ebp+0x00000008) 0x00000000/r32" "F - test-add-mem-to-reg")
27962     # . epilogue
27963     89/<- %esp 5/r32/ebp
27964     5d/pop-to-ebp
27965     c3/return
27966 
27967 test-add-literal-to-eax:
27968     #   var1/eax <- add 0x34
27969     # =>
27970     #   05/add-to-eax 0x34/imm32
27971     #
27972     # . prologue
27973     55/push-ebp
27974     89/<- %ebp 4/r32/esp
27975     # setup
27976     (clear-stream _test-output-stream)
27977     (clear-stream $_test-output-buffered-file->buffer)
27978 $test-add-literal-to-eax:initialize-var-type:
27979     # var type/ecx: (payload type-tree) = int
27980     68/push 0/imm32/right:null
27981     68/push 0/imm32/right:null
27982     68/push 0/imm32/left:unused
27983     68/push 1/imm32/value:int
27984     68/push 1/imm32/is-atom?:true
27985     68/push 0x11/imm32/alloc-id:fake:payload
27986     89/<- %ecx 4/r32/esp
27987 $test-add-literal-to-eax:initialize-var:
27988     # var v/ecx: (payload var)
27989     68/push 0/imm32/register
27990     68/push 0/imm32/register
27991     68/push 0/imm32/no-stack-offset
27992     68/push 1/imm32/block-depth
27993     51/push-ecx
27994     68/push 0x11/imm32/alloc-id:fake
27995     68/push 0/imm32/name
27996     68/push 0/imm32/name
27997     68/push 0x11/imm32/alloc-id:fake:payload
27998     89/<- %ecx 4/r32/esp
27999 $test-add-literal-to-eax:initialize-var-name:
28000     # v->name = "v"
28001     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
28002     (copy-array Heap "v" %eax)
28003 $test-add-literal-to-eax:initialize-var-register:
28004     # v->register = "eax"
28005     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
28006     (copy-array Heap "eax" %eax)
28007 $test-add-literal-to-eax:initialize-literal-type:
28008     # var type/edx: (payload type-tree) = literal
28009     68/push 0/imm32/right:null
28010     68/push 0/imm32/right:null
28011     68/push 0/imm32/left:unused
28012     68/push 0/imm32/value:literal
28013     68/push 1/imm32/is-atom?:true
28014     68/push 0x11/imm32/alloc-id:fake:payload
28015     89/<- %edx 4/r32/esp
28016 $test-add-literal-to-eax:initialize-literal:
28017     # var l/edx: (payload var)
28018     68/push 0/imm32/register
28019     68/push 0/imm32/register
28020     68/push 0/imm32/no-stack-offset
28021     68/push 1/imm32/block-depth
28022     52/push-edx
28023     68/push 0x11/imm32/alloc-id:fake
28024     68/push 0/imm32/name
28025     68/push 0/imm32/name
28026     68/push 0x11/imm32/alloc-id:fake:payload
28027     89/<- %edx 4/r32/esp
28028 $test-add-literal-to-eax:initialize-literal-value:
28029     # l->name = "0x34"
28030     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
28031     (copy-array Heap "0x34" %eax)
28032 $test-add-literal-to-eax:initialize-inouts:
28033     # var inouts/esi: (payload stmt-var) = [l]
28034     68/push 0/imm32/is-deref:false
28035     68/push 0/imm32/next
28036     68/push 0/imm32/next
28037     52/push-edx/l
28038     68/push 0x11/imm32/alloc-id:fake
28039     68/push 0x11/imm32/alloc-id:fake:payload
28040     89/<- %esi 4/r32/esp
28041 $test-add-literal-to-eax:initialize-outputs:
28042     # var outputs/edi: (payload stmt-var) = [v]
28043     68/push 0/imm32/is-deref:false
28044     68/push 0/imm32/next
28045     68/push 0/imm32/next
28046     51/push-ecx/v
28047     68/push 0x11/imm32/alloc-id:fake
28048     68/push 0x11/imm32/alloc-id:fake:payload
28049     89/<- %edi 4/r32/esp
28050 $test-add-literal-to-eax:initialize-stmt:
28051     # var stmt/esi: (addr statement)
28052     68/push 0/imm32/next
28053     68/push 0/imm32/next
28054     57/push-edi/outputs
28055     68/push 0x11/imm32/alloc-id:fake
28056     56/push-esi/inouts
28057     68/push 0x11/imm32/alloc-id:fake
28058     68/push 0/imm32/operation
28059     68/push 0/imm32/operation
28060     68/push 1/imm32/tag:stmt1
28061     89/<- %esi 4/r32/esp
28062 $test-add-literal-to-eax:initialize-stmt-operation:
28063     # stmt->operation = "add"
28064     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
28065     (copy-array Heap "add" %eax)
28066     # convert
28067     c7 0/subop/copy *Curr-block-depth 0/imm32
28068     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
28069     (flush _test-output-buffered-file)
28070 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
28076     # check output
28077     (check-next-stream-line-equal _test-output-stream "05/add-to-eax 0x34/imm32" "F - test-add-literal-to-eax")
28078     # . epilogue
28079     89/<- %esp 5/r32/ebp
28080     5d/pop-to-ebp
28081     c3/return
28082 
28083 test-add-literal-to-reg:
28084     #   var1/ecx <- add 0x34
28085     # =>
28086     #   81 0/subop/add %ecx 0x34/imm32
28087     #
28088     # . prologue
28089     55/push-ebp
28090     89/<- %ebp 4/r32/esp
28091     # setup
28092     (clear-stream _test-output-stream)
28093     (clear-stream $_test-output-buffered-file->buffer)
28094 $test-add-literal-to-reg:initialize-var-type:
28095     # var type/ecx: (payload type-tree) = int
28096     68/push 0/imm32/right:null
28097     68/push 0/imm32/right:null
28098     68/push 0/imm32/left:unused
28099     68/push 1/imm32/value:int
28100     68/push 1/imm32/is-atom?:true
28101     68/push 0x11/imm32/alloc-id:fake:payload
28102     89/<- %ecx 4/r32/esp
28103 $test-add-literal-to-reg:initialize-var:
28104     # var v/ecx: (payload var)
28105     68/push 0/imm32/register
28106     68/push 0/imm32/register
28107     68/push 0/imm32/no-stack-offset
28108     68/push 1/imm32/block-depth
28109     51/push-ecx
28110     68/push 0x11/imm32/alloc-id:fake
28111     68/push 0/imm32/name
28112     68/push 0/imm32/name
28113     68/push 0x11/imm32/alloc-id:fake:payload
28114     89/<- %ecx 4/r32/esp
28115 $test-add-literal-to-reg:initialize-var-name:
28116     # v->name = "v"
28117     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
28118     (copy-array Heap "v" %eax)
28119 $test-add-literal-to-reg:initialize-var-register:
28120     # v->register = "ecx"
28121     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
28122     (copy-array Heap "ecx" %eax)
28123 $test-add-literal-to-reg:initialize-literal-type:
28124     # var type/edx: (payload type-tree) = literal
28125     68/push 0/imm32/right:null
28126     68/push 0/imm32/right:null
28127     68/push 0/imm32/left:unused
28128     68/push 0/imm32/value:literal
28129     68/push 1/imm32/is-atom?:true
28130     68/push 0x11/imm32/alloc-id:fake:payload
28131     89/<- %edx 4/r32/esp
28132 $test-add-literal-to-reg:initialize-literal:
28133     # var l/edx: (payload var)
28134     68/push 0/imm32/register
28135     68/push 0/imm32/register
28136     68/push 0/imm32/no-stack-offset
28137     68/push 1/imm32/block-depth
28138     52/push-edx
28139     68/push 0x11/imm32/alloc-id:fake
28140     68/push 0/imm32/name
28141     68/push 0/imm32/name
28142     68/push 0x11/imm32/alloc-id:fake:payload
28143     89/<- %edx 4/r32/esp
28144 $test-add-literal-to-reg:initialize-literal-value:
28145     # l->name = "0x34"
28146     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
28147     (copy-array Heap "0x34" %eax)
28148 $test-add-literal-to-reg:initialize-inouts:
28149     # var inouts/esi: (payload stmt-var) = [l]
28150     68/push 0/imm32/is-deref:false
28151     68/push 0/imm32/next
28152     68/push 0/imm32/next
28153     52/push-edx/l
28154     68/push 0x11/imm32/alloc-id:fake
28155     68/push 0x11/imm32/alloc-id:fake:payload
28156     89/<- %esi 4/r32/esp
28157 $test-add-literal-to-reg:initialize-outputs:
28158     # var outputs/edi: (payload stmt-var) = [v]
28159     68/push 0/imm32/is-deref:false
28160     68/push 0/imm32/next
28161     68/push 0/imm32/next
28162     51/push-ecx/v
28163     68/push 0x11/imm32/alloc-id:fake
28164     68/push 0x11/imm32/alloc-id:fake:payload
28165     89/<- %edi 4/r32/esp
28166 $test-add-literal-to-reg:initialize-stmt:
28167     # var stmt/esi: (addr statement)
28168     68/push 0/imm32/next
28169     68/push 0/imm32/next
28170     57/push-edi/outputs
28171     68/push 0x11/imm32/alloc-id:fake
28172     56/push-esi/inouts
28173     68/push 0x11/imm32/alloc-id:fake
28174     68/push 0/imm32/operation
28175     68/push 0/imm32/operation
28176     68/push 1/imm32/tag:stmt1
28177     89/<- %esi 4/r32/esp
28178 $test-add-literal-to-reg:initialize-stmt-operation:
28179     # stmt->operation = "add"
28180     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
28181     (copy-array Heap "add" %eax)
28182     # convert
28183     c7 0/subop/copy *Curr-block-depth 0/imm32
28184     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
28185     (flush _test-output-buffered-file)
28186 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
28192     # check output
28193     (check-next-stream-line-equal _test-output-stream "81 0/subop/add %ecx 0x34/imm32" "F - test-add-literal-to-reg")
28194     # . epilogue
28195     89/<- %esp 5/r32/ebp
28196     5d/pop-to-ebp
28197     c3/return
28198 
28199 test-add-literal-to-mem:
28200     #   add-to var1, 0x34
28201     # =>
28202     #   81 0/subop/add %eax 0x34/imm32
28203     #
28204     # . prologue
28205     55/push-ebp
28206     89/<- %ebp 4/r32/esp
28207     # setup
28208     (clear-stream _test-output-stream)
28209     (clear-stream $_test-output-buffered-file->buffer)
28210 $test-add-literal-to-mem:initialize-type:
28211     # var type/ecx: (payload type-tree) = int
28212     68/push 0/imm32/right:null
28213     68/push 0/imm32/right:null
28214     68/push 0/imm32/left:unused
28215     68/push 1/imm32/value:int
28216     68/push 1/imm32/is-atom?:true
28217     68/push 0x11/imm32/alloc-id:fake:payload
28218     89/<- %ecx 4/r32/esp
28219 $test-add-literal-to-mem:initialize-var1:
28220     # var var1/ecx: (payload var)
28221     68/push 0/imm32/register
28222     68/push 0/imm32/register
28223     68/push 8/imm32/stack-offset
28224     68/push 1/imm32/block-depth
28225     51/push-ecx
28226     68/push 0x11/imm32/alloc-id:fake
28227     68/push 0/imm32/name
28228     68/push 0/imm32/name
28229     68/push 0x11/imm32/alloc-id:fake:payload
28230     89/<- %ecx 4/r32/esp
28231 $test-add-literal-to-mem:initialize-var1-name:
28232     # var1->name = "var1"
28233     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
28234     (copy-array Heap "var1" %eax)
28235 $test-add-literal-to-mem:initialize-literal-type:
28236     # var type/edx: (payload type-tree) = literal
28237     68/push 0/imm32/right:null
28238     68/push 0/imm32/right:null
28239     68/push 0/imm32/left:unused
28240     68/push 0/imm32/value:literal
28241     68/push 1/imm32/is-atom?:true
28242     68/push 0x11/imm32/alloc-id:fake:payload
28243     89/<- %edx 4/r32/esp
28244 $test-add-literal-to-mem:initialize-literal:
28245     # var l/edx: (payload var)
28246     68/push 0/imm32/register
28247     68/push 0/imm32/register
28248     68/push 0/imm32/no-stack-offset
28249     68/push 1/imm32/block-depth
28250     52/push-edx
28251     68/push 0x11/imm32/alloc-id:fake
28252     68/push 0/imm32/name
28253     68/push 0/imm32/name
28254     68/push 0x11/imm32/alloc-id:fake:payload
28255     89/<- %edx 4/r32/esp
28256 $test-add-literal-to-mem:initialize-literal-value:
28257     # l->name = "0x34"
28258     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
28259     (copy-array Heap "0x34" %eax)
28260 $test-add-literal-to-mem:initialize-inouts:
28261     # var inouts/esi: (payload stmt-var) = [l]
28262     68/push 0/imm32/is-deref:false
28263     68/push 0/imm32/next
28264     68/push 0/imm32/next
28265     52/push-edx/l
28266     68/push 0x11/imm32/alloc-id:fake
28267     68/push 0x11/imm32/alloc-id:fake:payload
28268     89/<- %esi 4/r32/esp
28269     # var inouts = (handle stmt-var) = [var1, var2]
28270     68/push 0/imm32/is-deref:false
28271     56/push-esi/next
28272     68/push 0x11/imm32/alloc-id:fake
28273     51/push-ecx/var1
28274     68/push 0x11/imm32/alloc-id:fake
28275     68/push 0x11/imm32/alloc-id:fake:payload
28276     89/<- %esi 4/r32/esp
28277 $test-add-literal-to-mem:initialize-stmt:
28278     # var stmt/esi: (addr statement)
28279     68/push 0/imm32/next
28280     68/push 0/imm32/next
28281     68/push 0/imm32/outputs
28282     68/push 0/imm32/outputs
28283     56/push-esi/inouts
28284     68/push 0x11/imm32/alloc-id:fake
28285     68/push 0/imm32/operation
28286     68/push 0/imm32/operation
28287     68/push 1/imm32/tag:stmt1
28288     89/<- %esi 4/r32/esp
28289 $test-add-literal-to-mem:initialize-stmt-operation:
28290     # stmt->operation = "add-to"
28291     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
28292     (copy-array Heap "add-to" %eax)
28293     # convert
28294     c7 0/subop/copy *Curr-block-depth 0/imm32
28295     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
28296     (flush _test-output-buffered-file)
28297 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
28303     # check output
28304     (check-next-stream-line-equal _test-output-stream "81 0/subop/add *(ebp+0x00000008) 0x34/imm32" "F - test-add-literal-to-mem")
28305     # . epilogue
28306     89/<- %esp 5/r32/ebp
28307     5d/pop-to-ebp
28308     c3/return
28309 
28310 test-shift-reg-by-literal:
28311     #   var1/ecx <- shift-left 2
28312     # =>
28313     #   c1/shift 4/subop/left %ecx 2/imm8
28314     #
28315     # . prologue
28316     55/push-ebp
28317     89/<- %ebp 4/r32/esp
28318     # setup
28319     (clear-stream _test-output-stream)
28320     (clear-stream $_test-output-buffered-file->buffer)
28321 $test-shift-reg-by-literal:initialize-var-type:
28322     # var type/ecx: (payload type-tree) = int
28323     68/push 0/imm32/right:null
28324     68/push 0/imm32/right:null
28325     68/push 0/imm32/left:unused
28326     68/push 1/imm32/value:int
28327     68/push 1/imm32/is-atom?:true
28328     68/push 0x11/imm32/alloc-id:fake:payload
28329     89/<- %ecx 4/r32/esp
28330 $test-shift-reg-by-literal:initialize-var:
28331     # var v/ecx: (payload var)
28332     68/push 0/imm32/register
28333     68/push 0/imm32/register
28334     68/push 0/imm32/no-stack-offset
28335     68/push 1/imm32/block-depth
28336     51/push-ecx
28337     68/push 0x11/imm32/alloc-id:fake
28338     68/push 0/imm32/name
28339     68/push 0/imm32/name
28340     68/push 0x11/imm32/alloc-id:fake:payload
28341     89/<- %ecx 4/r32/esp
28342 $test-shift-reg-by-literal:initialize-var-name:
28343     # v->name = "v"
28344     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
28345     (copy-array Heap "v" %eax)
28346 $test-shift-reg-by-literal:initialize-var-register:
28347     # v->register = "ecx"
28348     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
28349     (copy-array Heap "ecx" %eax)
28350 $test-shift-reg-by-literal:initialize-literal-type:
28351     # var type/edx: (payload type-tree) = literal
28352     68/push 0/imm32/right:null
28353     68/push 0/imm32/right:null
28354     68/push 0/imm32/left:unused
28355     68/push 0/imm32/value:literal
28356     68/push 1/imm32/is-atom?:true
28357     68/push 0x11/imm32/alloc-id:fake:payload
28358     89/<- %edx 4/r32/esp
28359 $test-shift-reg-by-literal:initialize-literal:
28360     # var l/edx: (payload var)
28361     68/push 0/imm32/register
28362     68/push 0/imm32/register
28363     68/push 0/imm32/no-stack-offset
28364     68/push 1/imm32/block-depth
28365     52/push-edx
28366     68/push 0x11/imm32/alloc-id:fake
28367     68/push 0/imm32/name
28368     68/push 0/imm32/name
28369     68/push 0x11/imm32/alloc-id:fake:payload
28370     89/<- %edx 4/r32/esp
28371 $test-shift-reg-by-literal:initialize-literal-value:
28372     # l->name = "2"
28373     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
28374     (copy-array Heap "2" %eax)
28375 $test-shift-reg-by-literal:initialize-inouts:
28376     # var inouts/esi: (payload stmt-var) = [l]
28377     68/push 0/imm32/is-deref:false
28378     68/push 0/imm32/next
28379     68/push 0/imm32/next
28380     52/push-edx/l
28381     68/push 0x11/imm32/alloc-id:fake
28382     68/push 0x11/imm32/alloc-id:fake:payload
28383     89/<- %esi 4/r32/esp
28384 $test-shift-reg-by-literal:initialize-outputs:
28385     # var outputs/edi: (payload stmt-var) = [v]
28386     68/push 0/imm32/is-deref:false
28387     68/push 0/imm32/next
28388     68/push 0/imm32/next
28389     51/push-ecx/v
28390     68/push 0x11/imm32/alloc-id:fake
28391     68/push 0x11/imm32/alloc-id:fake:payload
28392     89/<- %edi 4/r32/esp
28393 $test-shift-reg-by-literal:initialize-stmt:
28394     # var stmt/esi: (addr statement)
28395     68/push 0/imm32/next
28396     68/push 0/imm32/next
28397     57/push-edi/outputs
28398     68/push 0x11/imm32/alloc-id:fake
28399     56/push-esi/inouts
28400     68/push 0x11/imm32/alloc-id:fake
28401     68/push 0/imm32/operation
28402     68/push 0/imm32/operation
28403     68/push 1/imm32/tag:stmt1
28404     89/<- %esi 4/r32/esp
28405 $test-shift-reg-by-literal:initialize-stmt-operation:
28406     # stmt->operation = "shift-left"
28407     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
28408     (copy-array Heap "shift-left" %eax)
28409     # convert
28410     c7 0/subop/copy *Curr-block-depth 0/imm32
28411     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
28412     (flush _test-output-buffered-file)
28413 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
28419     # check output
28420     (check-next-stream-line-equal _test-output-stream "c1/shift 4/subop/left %ecx 2/imm8" "F - test-shift-reg-by-literal")
28421     # . epilogue
28422     89/<- %esp 5/r32/ebp
28423     5d/pop-to-ebp
28424     c3/return
28425 
28426 test-shift-mem-by-literal:
28427     #   shift-left var 3
28428     # =>
28429     #   c1/shift 4/subop/left *(ebp+8) 3/imm8
28430     #
28431     # . prologue
28432     55/push-ebp
28433     89/<- %ebp 4/r32/esp
28434     # setup
28435     (clear-stream _test-output-stream)
28436     (clear-stream $_test-output-buffered-file->buffer)
28437 $test-shift-mem-by-literal:initialize-type:
28438     # var type/ecx: (payload type-tree) = int
28439     68/push 0/imm32/right:null
28440     68/push 0/imm32/right:null
28441     68/push 0/imm32/left:unused
28442     68/push 1/imm32/value:int
28443     68/push 1/imm32/is-atom?:true
28444     68/push 0x11/imm32/alloc-id:fake:payload
28445     89/<- %ecx 4/r32/esp
28446 $test-shift-mem-by-literal:initialize-var1:
28447     # var var1/ecx: (payload var)
28448     68/push 0/imm32/register
28449     68/push 0/imm32/register
28450     68/push 8/imm32/stack-offset
28451     68/push 1/imm32/block-depth
28452     51/push-ecx
28453     68/push 0x11/imm32/alloc-id:fake
28454     68/push 0/imm32/name
28455     68/push 0/imm32/name
28456     68/push 0x11/imm32/alloc-id:fake:payload
28457     89/<- %ecx 4/r32/esp
28458 $test-shift-mem-by-literal:initialize-var1-name:
28459     # var1->name = "var1"
28460     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
28461     (copy-array Heap "var1" %eax)
28462 $test-shift-mem-by-literal:initialize-literal-type:
28463     # var type/edx: (payload type-tree) = literal
28464     68/push 0/imm32/right:null
28465     68/push 0/imm32/right:null
28466     68/push 0/imm32/left:unused
28467     68/push 0/imm32/value:literal
28468     68/push 1/imm32/is-atom?:true
28469     68/push 0x11/imm32/alloc-id:fake:payload
28470     89/<- %edx 4/r32/esp
28471 $test-shift-mem-by-literal:initialize-literal:
28472     # var l/edx: (payload var)
28473     68/push 0/imm32/register
28474     68/push 0/imm32/register
28475     68/push 0/imm32/no-stack-offset
28476     68/push 1/imm32/block-depth
28477     52/push-edx
28478     68/push 0x11/imm32/alloc-id:fake
28479     68/push 0/imm32/name
28480     68/push 0/imm32/name
28481     68/push 0x11/imm32/alloc-id:fake:payload
28482     89/<- %edx 4/r32/esp
28483 $test-shift-mem-by-literal:initialize-literal-value:
28484     # l->name = "3"
28485     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
28486     (copy-array Heap "3" %eax)
28487 $test-shift-mem-by-literal:initialize-inouts:
28488     # var inouts/esi: (payload stmt-var) = [l]
28489     68/push 0/imm32/is-deref:false
28490     68/push 0/imm32/next
28491     68/push 0/imm32/next
28492     52/push-edx/l
28493     68/push 0x11/imm32/alloc-id:fake
28494     68/push 0x11/imm32/alloc-id:fake:payload
28495     89/<- %esi 4/r32/esp
28496     # var inouts = (handle stmt-var) = [var1, var2]
28497     68/push 0/imm32/is-deref:false
28498     56/push-esi/next
28499     68/push 0x11/imm32/alloc-id:fake
28500     51/push-ecx/var1
28501     68/push 0x11/imm32/alloc-id:fake
28502     68/push 0x11/imm32/alloc-id:fake:payload
28503     89/<- %esi 4/r32/esp
28504 $test-shift-mem-by-literal:initialize-stmt:
28505     # var stmt/esi: (addr statement)
28506     68/push 0/imm32/next
28507     68/push 0/imm32/next
28508     68/push 0/imm32/outputs
28509     68/push 0/imm32/outputs
28510     56/push-esi/inouts
28511     68/push 0x11/imm32/alloc-id:fake
28512     68/push 0/imm32/operation
28513     68/push 0/imm32/operation
28514     68/push 1/imm32/tag:stmt1
28515     89/<- %esi 4/r32/esp
28516 $test-shift-mem-by-literal:initialize-stmt-operation:
28517     # stmt->operation = "shift-left"
28518     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
28519     (copy-array Heap "shift-left" %eax)
28520     # convert
28521     c7 0/subop/copy *Curr-block-depth 0/imm32
28522     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
28523     (flush _test-output-buffered-file)
28524 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
28530     # check output
28531     (check-next-stream-line-equal _test-output-stream "c1/shift 4/subop/left *(ebp+0x00000008) 3/imm8" "F - test-shift-mem-by-literal")
28532     # . epilogue
28533     89/<- %esp 5/r32/ebp
28534     5d/pop-to-ebp
28535     c3/return
28536 
28537 test-compare-reg-with-reg:
28538     #   compare var1/ecx, var2/eax
28539     # =>
28540     #   39/compare %ecx 0/r32/eax
28541     #
28542     # . prologue
28543     55/push-ebp
28544     89/<- %ebp 4/r32/esp
28545     # setup
28546     (clear-stream _test-output-stream)
28547     (clear-stream $_test-output-buffered-file->buffer)
28548 $test-compare-reg-with-reg:initialize-type:
28549     # var type/ecx: (payload type-tree) = int
28550     68/push 0/imm32/right:null
28551     68/push 0/imm32/right:null
28552     68/push 0/imm32/left:unused
28553     68/push 1/imm32/value:int
28554     68/push 1/imm32/is-atom?:true
28555     68/push 0x11/imm32/alloc-id:fake:payload
28556     89/<- %ecx 4/r32/esp
28557 $test-compare-reg-with-reg:initialize-var1:
28558     # var var1/ecx: (payload var)
28559     68/push 0/imm32/register
28560     68/push 0/imm32/register
28561     68/push 0/imm32/no-stack-offset
28562     68/push 1/imm32/block-depth
28563     51/push-ecx
28564     68/push 0x11/imm32/alloc-id:fake
28565     68/push 0/imm32/name
28566     68/push 0/imm32/name
28567     68/push 0x11/imm32/alloc-id:fake:payload
28568     89/<- %ecx 4/r32/esp
28569 $test-compare-reg-with-reg:initialize-var1-name:
28570     # var1->name = "var1"
28571     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
28572     (copy-array Heap "var1" %eax)
28573 $test-compare-reg-with-reg:initialize-var1-register:
28574     # var1->register = "ecx"
28575     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
28576     (copy-array Heap "ecx" %eax)
28577 $test-compare-reg-with-reg:initialize-var2:
28578     # var var2/edx: (payload var)
28579     68/push 0/imm32/register
28580     68/push 0/imm32/register
28581     68/push 0/imm32/no-stack-offset
28582     68/push 1/imm32/block-depth
28583     ff 6/subop/push *(ecx+0x10)
28584     68/push 0x11/imm32/alloc-id:fake
28585     68/push 0/imm32/name
28586     68/push 0/imm32/name
28587     68/push 0x11/imm32/alloc-id:fake:payload
28588     89/<- %edx 4/r32/esp
28589 $test-compare-reg-with-reg:initialize-var2-name:
28590     # var2->name = "var2"
28591     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
28592     (copy-array Heap "var2" %eax)
28593 $test-compare-reg-with-reg:initialize-var2-register:
28594     # var2->register = "eax"
28595     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
28596     (copy-array Heap "eax" %eax)
28597 $test-compare-reg-with-reg:initialize-inouts:
28598     # var inouts/esi: (payload stmt-var) = [var2]
28599     68/push 0/imm32/is-deref:false
28600     68/push 0/imm32/next
28601     68/push 0/imm32/next
28602     52/push-edx/var2
28603     68/push 0x11/imm32/alloc-id:fake
28604     68/push 0x11/imm32/alloc-id:fake:payload
28605     89/<- %esi 4/r32/esp
28606     # inouts = [var1, var2]
28607     68/push 0/imm32/is-deref:false
28608     56/push-esi/next
28609     68/push 0x11/imm32/alloc-id:fake
28610     51/push-ecx/var1
28611     68/push 0x11/imm32/alloc-id:fake
28612     68/push 0x11/imm32/alloc-id:fake:payload
28613     89/<- %esi 4/r32/esp
28614 $test-compare-reg-with-reg:initialize-stmt:
28615     # var stmt/esi: (addr statement)
28616     68/push 0/imm32/next
28617     68/push 0/imm32/next
28618     68/push 0/imm32/outputs
28619     68/push 0/imm32/outputs
28620     56/push-esi/inouts
28621     68/push 0x11/imm32/alloc-id:fake
28622     68/push 0/imm32/operation
28623     68/push 0/imm32/operation
28624     68/push 1/imm32/tag:stmt1
28625     89/<- %esi 4/r32/esp
28626 $test-compare-reg-with-reg:initialize-stmt-operation:
28627     # stmt->operation = "compare"
28628     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
28629     (copy-array Heap "compare" %eax)
28630     # convert
28631     c7 0/subop/copy *Curr-block-depth 0/imm32
28632     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
28633     (flush _test-output-buffered-file)
28634 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
28640     # check output
28641     (check-next-stream-line-equal _test-output-stream "39/compare-> %ecx 0x00000000/r32" "F - test-compare-reg-with-reg")
28642     # . epilogue
28643     89/<- %esp 5/r32/ebp
28644     5d/pop-to-ebp
28645     c3/return
28646 
28647 test-compare-mem-with-reg:
28648     #   compare var1, var2/eax
28649     # =>
28650     #   39/compare *(ebp+___) 0/r32/eax
28651     #
28652     # . prologue
28653     55/push-ebp
28654     89/<- %ebp 4/r32/esp
28655     # setup
28656     (clear-stream _test-output-stream)
28657     (clear-stream $_test-output-buffered-file->buffer)
28658 $test-compare-mem-with-reg:initialize-type:
28659     # var type/ecx: (payload type-tree) = int
28660     68/push 0/imm32/right:null
28661     68/push 0/imm32/right:null
28662     68/push 0/imm32/left:unused
28663     68/push 1/imm32/value:int
28664     68/push 1/imm32/is-atom?:true
28665     68/push 0x11/imm32/alloc-id:fake:payload
28666     89/<- %ecx 4/r32/esp
28667 $test-compare-mem-with-reg:initialize-var1:
28668     # var var1/ecx: (payload var)
28669     68/push 0/imm32/register
28670     68/push 0/imm32/register
28671     68/push 8/imm32/stack-offset
28672     68/push 1/imm32/block-depth
28673     51/push-ecx
28674     68/push 0x11/imm32/alloc-id:fake
28675     68/push 0/imm32/name
28676     68/push 0/imm32/name
28677     68/push 0x11/imm32/alloc-id:fake:payload
28678     89/<- %ecx 4/r32/esp
28679 $test-compare-mem-with-reg:initialize-var1-name:
28680     # var1->name = "var1"
28681     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
28682     (copy-array Heap "var1" %eax)
28683 $test-compare-mem-with-reg:initialize-var2:
28684     # var var2/edx: (payload var)
28685     68/push 0/imm32/register
28686     68/push 0/imm32/register
28687     68/push 0/imm32/no-stack-offset
28688     68/push 1/imm32/block-depth
28689     ff 6/subop/push *(ecx+0x10)
28690     68/push 0x11/imm32/alloc-id:fake
28691     68/push 0/imm32/name
28692     68/push 0/imm32/name
28693     68/push 0x11/imm32/alloc-id:fake:payload
28694     89/<- %edx 4/r32/esp
28695 $test-compare-mem-with-reg:initialize-var2-name:
28696     # var2->name = "var2"
28697     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
28698     (copy-array Heap "var2" %eax)
28699 $test-compare-mem-with-reg:initialize-var2-register:
28700     # var2->register = "eax"
28701     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
28702     (copy-array Heap "eax" %eax)
28703 $test-compare-mem-with-reg:initialize-inouts:
28704     # var inouts/esi: (payload stmt-var) = [var2]
28705     68/push 0/imm32/is-deref:false
28706     68/push 0/imm32/next
28707     68/push 0/imm32/next
28708     52/push-edx/var2
28709     68/push 0x11/imm32/alloc-id:fake
28710     68/push 0x11/imm32/alloc-id:fake:payload
28711     89/<- %esi 4/r32/esp
28712     # inouts = [var1, var2]
28713     68/push 0/imm32/is-deref:false
28714     56/push-esi/next
28715     68/push 0x11/imm32/alloc-id:fake
28716     51/push-ecx/var1
28717     68/push 0x11/imm32/alloc-id:fake
28718     68/push 0x11/imm32/alloc-id:fake:payload
28719     89/<- %esi 4/r32/esp
28720 $test-compare-mem-with-reg:initialize-stmt:
28721     # var stmt/esi: (addr statement)
28722     68/push 0/imm32/next
28723     68/push 0/imm32/next
28724     68/push 0/imm32/outputs
28725     68/push 0/imm32/outputs
28726     56/push-esi/inouts
28727     68/push 0x11/imm32/alloc-id:fake
28728     68/push 0/imm32/operation
28729     68/push 0/imm32/operation
28730     68/push 1/imm32/tag:stmt1
28731     89/<- %esi 4/r32/esp
28732 $test-compare-mem-with-reg:initialize-stmt-operation:
28733     # stmt->operation = "compare"
28734     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
28735     (copy-array Heap "compare" %eax)
28736     # convert
28737     c7 0/subop/copy *Curr-block-depth 0/imm32
28738     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
28739     (flush _test-output-buffered-file)
28740 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
28746     # check output
28747     (check-next-stream-line-equal _test-output-stream "39/compare-> *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-mem-with-reg")
28748     # . epilogue
28749     89/<- %esp 5/r32/ebp
28750     5d/pop-to-ebp
28751     c3/return
28752 
28753 test-compare-reg-with-mem:
28754     #   compare var1/eax, var2
28755     # =>
28756     #   3b/compare<- *(ebp+___) 0/r32/eax
28757     #
28758     # . prologue
28759     55/push-ebp
28760     89/<- %ebp 4/r32/esp
28761     # setup
28762     (clear-stream _test-output-stream)
28763     (clear-stream $_test-output-buffered-file->buffer)
28764 $test-compare-reg-with-mem:initialize-type:
28765     # var type/ecx: (payload type-tree) = int
28766     68/push 0/imm32/right:null
28767     68/push 0/imm32/right:null
28768     68/push 0/imm32/left:unused
28769     68/push 1/imm32/value:int
28770     68/push 1/imm32/is-atom?:true
28771     68/push 0x11/imm32/alloc-id:fake:payload
28772     89/<- %ecx 4/r32/esp
28773 $test-compare-reg-with-mem:initialize-var1:
28774     # var var1/ecx: (payload var)
28775     68/push 0/imm32/register
28776     68/push 0/imm32/register
28777     68/push 0/imm32/no-stack-offset
28778     68/push 1/imm32/block-depth
28779     51/push-ecx
28780     68/push 0x11/imm32/alloc-id:fake
28781     68/push 0/imm32/name
28782     68/push 0/imm32/name
28783     68/push 0x11/imm32/alloc-id:fake:payload
28784     89/<- %ecx 4/r32/esp
28785 $test-compare-reg-with-mem:initialize-var1-name:
28786     # var1->name = "var1"
28787     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
28788     (copy-array Heap "var1" %eax)
28789 $test-compare-reg-with-mem:initialize-var1-register:
28790     # var1->register = "eax"
28791     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
28792     (copy-array Heap "eax" %eax)
28793 $test-compare-reg-with-mem:initialize-var2:
28794     # var var2/edx: (payload var)
28795     68/push 0/imm32/register
28796     68/push 0/imm32/register
28797     68/push 8/imm32/stack-offset
28798     68/push 1/imm32/block-depth
28799     ff 6/subop/push *(ecx+0x10)
28800     68/push 0x11/imm32/alloc-id:fake
28801     68/push 0/imm32/name
28802     68/push 0/imm32/name
28803     68/push 0x11/imm32/alloc-id:fake:payload
28804     89/<- %edx 4/r32/esp
28805 $test-compare-reg-with-mem:initialize-var2-name:
28806     # var2->name = "var2"
28807     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
28808     (copy-array Heap "var2" %eax)
28809 $test-compare-reg-with-mem:initialize-inouts:
28810     # var inouts/esi: (payload stmt-var) = [var2]
28811     68/push 0/imm32/is-deref:false
28812     68/push 0/imm32/next
28813     68/push 0/imm32/next
28814     52/push-edx/var2
28815     68/push 0x11/imm32/alloc-id:fake
28816     68/push 0x11/imm32/alloc-id:fake:payload
28817     89/<- %esi 4/r32/esp
28818     # inouts = [var1, var2]
28819     68/push 0/imm32/is-deref:false
28820     56/push-esi/next
28821     68/push 0x11/imm32/alloc-id:fake
28822     51/push-ecx/var1
28823     68/push 0x11/imm32/alloc-id:fake
28824     68/push 0x11/imm32/alloc-id:fake:payload
28825     89/<- %esi 4/r32/esp
28826 $test-compare-reg-with-mem:initialize-stmt:
28827     # var stmt/esi: (addr statement)
28828     68/push 0/imm32/next
28829     68/push 0/imm32/next
28830     68/push 0/imm32/outputs
28831     68/push 0/imm32/outputs
28832     56/push-esi/inouts
28833     68/push 0x11/imm32/alloc-id:fake
28834     68/push 0/imm32/operation
28835     68/push 0/imm32/operation
28836     68/push 1/imm32/tag:stmt1
28837     89/<- %esi 4/r32/esp
28838 $test-compare-reg-with-mem:initialize-stmt-operation:
28839     # stmt->operation = "compare"
28840     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
28841     (copy-array Heap "compare" %eax)
28842     # convert
28843     c7 0/subop/copy *Curr-block-depth 0/imm32
28844     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
28845     (flush _test-output-buffered-file)
28846 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
28852     # check output
28853     (check-next-stream-line-equal _test-output-stream "3b/compare<- *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-reg-with-mem")
28854     # . epilogue
28855     89/<- %esp 5/r32/ebp
28856     5d/pop-to-ebp
28857     c3/return
28858 
28859 test-compare-mem-with-literal:
28860     #   compare var1, 0x34
28861     # =>
28862     #   81 7/subop/compare *(ebp+___) 0x34/imm32
28863     #
28864     # . prologue
28865     55/push-ebp
28866     89/<- %ebp 4/r32/esp
28867     # setup
28868     (clear-stream _test-output-stream)
28869     (clear-stream $_test-output-buffered-file->buffer)
28870 $test-compare-mem-with-literal:initialize-type:
28871     # var type/ecx: (payload type-tree) = int
28872     68/push 0/imm32/right:null
28873     68/push 0/imm32/right:null
28874     68/push 0/imm32/left:unused
28875     68/push 1/imm32/value:int
28876     68/push 1/imm32/is-atom?:true
28877     68/push 0x11/imm32/alloc-id:fake:payload
28878     89/<- %ecx 4/r32/esp
28879 $test-compare-mem-with-literal:initialize-var1:
28880     # var var1/ecx: (payload var)
28881     68/push 0/imm32/register
28882     68/push 0/imm32/register
28883     68/push 8/imm32/stack-offset
28884     68/push 1/imm32/block-depth
28885     51/push-ecx
28886     68/push 0x11/imm32/alloc-id:fake
28887     68/push 0/imm32/name
28888     68/push 0/imm32/name
28889     68/push 0x11/imm32/alloc-id:fake:payload
28890     89/<- %ecx 4/r32/esp
28891 $test-compare-mem-with-literal:initialize-var1-name:
28892     # var1->name = "var1"
28893     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
28894     (copy-array Heap "var1" %eax)
28895 $test-compare-mem-with-literal:initialize-literal-type:
28896     # var type/edx: (payload type-tree) = literal
28897     68/push 0/imm32/right:null
28898     68/push 0/imm32/right:null
28899     68/push 0/imm32/left:unused
28900     68/push 0/imm32/value:literal
28901     68/push 1/imm32/is-atom?:true
28902     68/push 0x11/imm32/alloc-id:fake:payload
28903     89/<- %edx 4/r32/esp
28904 $test-compare-mem-with-literal:initialize-literal:
28905     # var l/edx: (payload var)
28906     68/push 0/imm32/register
28907     68/push 0/imm32/register
28908     68/push 0/imm32/no-stack-offset
28909     68/push 1/imm32/block-depth
28910     52/push-edx
28911     68/push 0x11/imm32/alloc-id:fake
28912     68/push 0/imm32/name
28913     68/push 0/imm32/name
28914     68/push 0x11/imm32/alloc-id:fake:payload
28915     89/<- %edx 4/r32/esp
28916 $test-compare-mem-with-literal:initialize-literal-value:
28917     # l->name = "0x34"
28918     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
28919     (copy-array Heap "0x34" %eax)
28920 $test-compare-mem-with-literal:initialize-inouts:
28921     # var inouts/esi: (payload stmt-var) = [l]
28922     68/push 0/imm32/is-deref:false
28923     68/push 0/imm32/next
28924     68/push 0/imm32/next
28925     52/push-edx/l
28926     68/push 0x11/imm32/alloc-id:fake
28927     68/push 0x11/imm32/alloc-id:fake:payload
28928     89/<- %esi 4/r32/esp
28929     # var inouts = (handle stmt-var) = [var1, var2]
28930     68/push 0/imm32/is-deref:false
28931     56/push-esi/next
28932     68/push 0x11/imm32/alloc-id:fake
28933     51/push-ecx/var1
28934     68/push 0x11/imm32/alloc-id:fake
28935     68/push 0x11/imm32/alloc-id:fake:payload
28936     89/<- %esi 4/r32/esp
28937 $test-compare-mem-with-literal:initialize-stmt:
28938     # var stmt/esi: (addr statement)
28939     68/push 0/imm32/next
28940     68/push 0/imm32/next
28941     68/push 0/imm32/outputs
28942     68/push 0/imm32/outputs
28943     56/push-esi/inouts
28944     68/push 0x11/imm32/alloc-id:fake
28945     68/push 0/imm32/operation
28946     68/push 0/imm32/operation
28947     68/push 1/imm32/tag:stmt1
28948     89/<- %esi 4/r32/esp
28949 $test-compare-mem-with-literal:initialize-stmt-operation:
28950     # stmt->operation = "compare"
28951     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
28952     (copy-array Heap "compare" %eax)
28953     # convert
28954     c7 0/subop/copy *Curr-block-depth 0/imm32
28955     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
28956     (flush _test-output-buffered-file)
28957 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
28963     # check output
28964     (check-next-stream-line-equal _test-output-stream "81 7/subop/compare *(ebp+0x00000008) 0x34/imm32" "F - test-compare-mem-with-literal")
28965     # . epilogue
28966     89/<- %esp 5/r32/ebp
28967     5d/pop-to-ebp
28968     c3/return
28969 
28970 test-compare-eax-with-literal:
28971     #   compare var1/eax 0x34
28972     # =>
28973     #   3d/compare-eax-with 0x34/imm32
28974     #
28975     # . prologue
28976     55/push-ebp
28977     89/<- %ebp 4/r32/esp
28978     # setup
28979     (clear-stream _test-output-stream)
28980     (clear-stream $_test-output-buffered-file->buffer)
28981 $test-compare-eax-with-literal:initialize-type:
28982     # var type/ecx: (payload type-tree) = int
28983     68/push 0/imm32/right:null
28984     68/push 0/imm32/right:null
28985     68/push 0/imm32/left:unused
28986     68/push 1/imm32/value:int
28987     68/push 1/imm32/is-atom?:true
28988     68/push 0x11/imm32/alloc-id:fake:payload
28989     89/<- %ecx 4/r32/esp
28990 $test-compare-eax-with-literal:initialize-var1:
28991     # var var1/ecx: (payload var)
28992     68/push 0/imm32/register
28993     68/push 0/imm32/register
28994     68/push 0/imm32/no-stack-offset
28995     68/push 1/imm32/block-depth
28996     51/push-ecx
28997     68/push 0x11/imm32/alloc-id:fake
28998     68/push 0/imm32/name
28999     68/push 0/imm32/name
29000     68/push 0x11/imm32/alloc-id:fake:payload
29001     89/<- %ecx 4/r32/esp
29002 $test-compare-eax-with-literal:initialize-var1-name:
29003     # var1->name = "var1"
29004     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
29005     (copy-array Heap "var1" %eax)
29006 $test-compare-eax-with-literal:initialize-var1-register:
29007     # v->register = "eax"
29008     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
29009     (copy-array Heap "eax" %eax)
29010 $test-compare-eax-with-literal:initialize-literal-type:
29011     # var type/edx: (payload type-tree) = literal
29012     68/push 0/imm32/right:null
29013     68/push 0/imm32/right:null
29014     68/push 0/imm32/left:unused
29015     68/push 0/imm32/value:literal
29016     68/push 1/imm32/is-atom?:true
29017     68/push 0x11/imm32/alloc-id:fake:payload
29018     89/<- %edx 4/r32/esp
29019 $test-compare-eax-with-literal:initialize-literal:
29020     # var l/edx: (payload var)
29021     68/push 0/imm32/register
29022     68/push 0/imm32/register
29023     68/push 0/imm32/no-stack-offset
29024     68/push 1/imm32/block-depth
29025     52/push-edx
29026     68/push 0x11/imm32/alloc-id:fake
29027     68/push 0/imm32/name
29028     68/push 0/imm32/name
29029     68/push 0x11/imm32/alloc-id:fake:payload
29030     89/<- %edx 4/r32/esp
29031 $test-compare-eax-with-literal:initialize-literal-value:
29032     # l->name = "0x34"
29033     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
29034     (copy-array Heap "0x34" %eax)
29035 $test-compare-eax-with-literal:initialize-inouts:
29036     # var inouts/esi: (payload stmt-var) = [l]
29037     68/push 0/imm32/is-deref:false
29038     68/push 0/imm32/next
29039     68/push 0/imm32/next
29040     52/push-edx/l
29041     68/push 0x11/imm32/alloc-id:fake
29042     68/push 0x11/imm32/alloc-id:fake:payload
29043     89/<- %esi 4/r32/esp
29044     # var inouts = (handle stmt-var) = [var1, var2]
29045     68/push 0/imm32/is-deref:false
29046     56/push-esi/next
29047     68/push 0x11/imm32/alloc-id:fake
29048     51/push-ecx/var1
29049     68/push 0x11/imm32/alloc-id:fake
29050     68/push 0x11/imm32/alloc-id:fake:payload
29051     89/<- %esi 4/r32/esp
29052 $test-compare-eax-with-literal:initialize-stmt:
29053     # var stmt/esi: (addr statement)
29054     68/push 0/imm32/next
29055     68/push 0/imm32/next
29056     68/push 0/imm32/outputs
29057     68/push 0/imm32/outputs
29058     56/push-esi/inouts
29059     68/push 0x11/imm32/alloc-id:fake
29060     68/push 0/imm32/operation
29061     68/push 0/imm32/operation
29062     68/push 1/imm32/tag:stmt1
29063     89/<- %esi 4/r32/esp
29064 $test-compare-eax-with-literal:initialize-stmt-operation:
29065     # stmt->operation = "compare"
29066     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
29067     (copy-array Heap "compare" %eax)
29068     # convert
29069     c7 0/subop/copy *Curr-block-depth 0/imm32
29070     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
29071     (flush _test-output-buffered-file)
29072 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
29078     # check output
29079     (check-next-stream-line-equal _test-output-stream "3d/compare-eax-with 0x34/imm32" "F - test-compare-eax-with-literal")
29080     # . epilogue
29081     89/<- %esp 5/r32/ebp
29082     5d/pop-to-ebp
29083     c3/return
29084 
29085 test-compare-reg-with-literal:
29086     #   compare var1/ecx 0x34
29087     # =>
29088     #   81 7/subop/compare %ecx 0x34/imm32
29089     #
29090     # . prologue
29091     55/push-ebp
29092     89/<- %ebp 4/r32/esp
29093     # setup
29094     (clear-stream _test-output-stream)
29095     (clear-stream $_test-output-buffered-file->buffer)
29096 $test-compare-reg-with-literal:initialize-type:
29097     # var type/ecx: (payload type-tree) = int
29098     68/push 0/imm32/right:null
29099     68/push 0/imm32/right:null
29100     68/push 0/imm32/left:unused
29101     68/push 1/imm32/value:int
29102     68/push 1/imm32/is-atom?:true
29103     68/push 0x11/imm32/alloc-id:fake:payload
29104     89/<- %ecx 4/r32/esp
29105 $test-compare-reg-with-literal:initialize-var1:
29106     # var var1/ecx: (payload var)
29107     68/push 0/imm32/register
29108     68/push 0/imm32/register
29109     68/push 0/imm32/no-stack-offset
29110     68/push 1/imm32/block-depth
29111     51/push-ecx
29112     68/push 0x11/imm32/alloc-id:fake
29113     68/push 0/imm32/name
29114     68/push 0/imm32/name
29115     68/push 0x11/imm32/alloc-id:fake:payload
29116     89/<- %ecx 4/r32/esp
29117 $test-compare-reg-with-literal:initialize-var1-name:
29118     # var1->name = "var1"
29119     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
29120     (copy-array Heap "var1" %eax)
29121 $test-compare-reg-with-literal:initialize-var1-register:
29122     # v->register = "ecx"
29123     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
29124     (copy-array Heap "ecx" %eax)
29125 $test-compare-reg-with-literal:initialize-literal-type:
29126     # var type/edx: (payload type-tree) = literal
29127     68/push 0/imm32/right:null
29128     68/push 0/imm32/right:null
29129     68/push 0/imm32/left:unused
29130     68/push 0/imm32/value:literal
29131     68/push 1/imm32/is-atom?:true
29132     68/push 0x11/imm32/alloc-id:fake:payload
29133     89/<- %edx 4/r32/esp
29134 $test-compare-reg-with-literal:initialize-literal:
29135     # var l/edx: (payload var)
29136     68/push 0/imm32/register
29137     68/push 0/imm32/register
29138     68/push 0/imm32/no-stack-offset
29139     68/push 1/imm32/block-depth
29140     52/push-edx
29141     68/push 0x11/imm32/alloc-id:fake
29142     68/push 0/imm32/name
29143     68/push 0/imm32/name
29144     68/push 0x11/imm32/alloc-id:fake:payload
29145     89/<- %edx 4/r32/esp
29146 $test-compare-reg-with-literal:initialize-literal-value:
29147     # l->name = "0x34"
29148     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
29149     (copy-array Heap "0x34" %eax)
29150 $test-compare-reg-with-literal:initialize-inouts:
29151     # var inouts/esi: (payload stmt-var) = [l]
29152     68/push 0/imm32/is-deref:false
29153     68/push 0/imm32/next
29154     68/push 0/imm32/next
29155     52/push-edx/l
29156     68/push 0x11/imm32/alloc-id:fake
29157     68/push 0x11/imm32/alloc-id:fake:payload
29158     89/<- %esi 4/r32/esp
29159     # var inouts = (handle stmt-var) = [var1, var2]
29160     68/push 0/imm32/is-deref:false
29161     56/push-esi/next
29162     68/push 0x11/imm32/alloc-id:fake
29163     51/push-ecx/var1
29164     68/push 0x11/imm32/alloc-id:fake
29165     68/push 0x11/imm32/alloc-id:fake:payload
29166     89/<- %esi 4/r32/esp
29167 $test-compare-reg-with-literal:initialize-stmt:
29168     # var stmt/esi: (addr statement)
29169     68/push 0/imm32/next
29170     68/push 0/imm32/next
29171     68/push 0/imm32/outputs
29172     68/push 0/imm32/outputs
29173     56/push-esi/inouts
29174     68/push 0x11/imm32/alloc-id:fake
29175     68/push 0/imm32/operation
29176     68/push 0/imm32/operation
29177     68/push 1/imm32/tag:stmt1
29178     89/<- %esi 4/r32/esp
29179 $test-compare-reg-with-literal:initialize-stmt-operation:
29180     # stmt->operation = "compare"
29181     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
29182     (copy-array Heap "compare" %eax)
29183     # convert
29184     c7 0/subop/copy *Curr-block-depth 0/imm32
29185     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
29186     (flush _test-output-buffered-file)
29187 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
29193     # check output
29194     (check-next-stream-line-equal _test-output-stream "81 7/subop/compare %ecx 0x34/imm32" "F - test-compare-reg-with-literal")
29195     # . epilogue
29196     89/<- %esp 5/r32/ebp
29197     5d/pop-to-ebp
29198     c3/return
29199 
29200 test-emit-subx-stmt-function-call:
29201     # Call a function on a variable on the stack.
29202     #   f foo
29203     # =>
29204     #   (f *(ebp-8))
29205     # (Changing the function name supports overloading in general, but here it
29206     # just serves to help disambiguate things.)
29207     #
29208     # There's a variable on the var stack as follows:
29209     #   name: 'foo'
29210     #   type: int
29211     #   stack-offset: -8
29212     #
29213     # There's nothing in primitives.
29214     #
29215     # We don't perform any checking here on the type of 'f'.
29216     #
29217     # . prologue
29218     55/push-ebp
29219     89/<- %ebp 4/r32/esp
29220     # setup
29221     (clear-stream _test-output-stream)
29222     (clear-stream $_test-output-buffered-file->buffer)
29223 $test-emit-subx-function-call:initialize-type:
29224     # var type/ecx: (payload type-tree) = int
29225     68/push 0/imm32/right:null
29226     68/push 0/imm32/right:null
29227     68/push 0/imm32/left:unused
29228     68/push 1/imm32/value:int
29229     68/push 1/imm32/is-atom?:true
29230     68/push 0x11/imm32/alloc-id:fake:payload
29231     89/<- %ecx 4/r32/esp
29232 $test-emit-subx-function-call:initialize-var:
29233     # var var-foo/ecx: (payload var) = var(type)
29234     68/push 0/imm32/no-register
29235     68/push 0/imm32/no-register
29236     68/push -8/imm32/stack-offset
29237     68/push 1/imm32/block-depth
29238     51/push-ecx/type
29239     68/push 0x11/imm32/alloc-id:fake
29240     68/push 0/imm32/name
29241     68/push 0/imm32/name
29242     68/push 0x11/imm32/alloc-id:fake:payload
29243     89/<- %ecx 4/r32/esp
29244 $test-emit-subx-function-call:initialize-var-name:
29245     # var-foo->name = "foo"
29246     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
29247     (copy-array Heap "foo" %eax)
29248 $test-emit-subx-function-call:initialize-stmt-var:
29249     # var operand/ebx: (payload stmt-var) = stmt-var(var-foo)
29250     68/push 0/imm32/is-deref:false
29251     68/push 0/imm32/next
29252     68/push 0/imm32/next
29253     51/push-ecx/var-foo
29254     68/push 0x11/imm32/alloc-id:fake
29255     68/push 0x11/imm32/alloc-id:fake:payload
29256     89/<- %ebx 4/r32/esp
29257 $test-emit-subx-function-call:initialize-stmt:
29258     # var stmt/esi: (addr statement)
29259     68/push 0/imm32/no-outputs
29260     68/push 0/imm32/no-outputs
29261     53/push-ebx/inouts
29262     68/push 0x11/imm32/alloc-id:fake
29263     68/push 0/imm32/operation
29264     68/push 0/imm32/operation
29265     68/push 1/imm32/tag
29266     89/<- %esi 4/r32/esp
29267 $test-emit-subx-function-call:initialize-stmt-operation:
29268     # stmt->operation = "f"
29269     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
29270     (copy-array Heap "f" %eax)
29271     # convert
29272     c7 0/subop/copy *Curr-block-depth 0/imm32
29273     (emit-subx-stmt _test-output-buffered-file %esi 0 Stderr 0)
29274     (flush _test-output-buffered-file)
29275 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
29281     # check output
29282     (check-next-stream-line-equal _test-output-stream "(f *(ebp+0xfffffff8))" "F - test-emit-subx-stmt-function-call")
29283     # . epilogue
29284     89/<- %esp 5/r32/ebp
29285     5d/pop-to-ebp
29286     c3/return
29287 
29288 test-emit-subx-stmt-function-call-with-literal-arg:
29289     # Call a function on a literal.
29290     #   f 0x34
29291     # =>
29292     #   (f2 0x34)
29293     #
29294     # . prologue
29295     55/push-ebp
29296     89/<- %ebp 4/r32/esp
29297     # setup
29298     (clear-stream _test-output-stream)
29299     (clear-stream $_test-output-buffered-file->buffer)
29300 $test-emit-subx-function-call-with-literal-arg:initialize-type:
29301     # var type/ecx: (payload type-tree) = int
29302     68/push 0/imm32/right:null
29303     68/push 0/imm32/right:null
29304     68/push 0/imm32/left:unused
29305     68/push 0/imm32/value:literal
29306     68/push 1/imm32/is-atom?:true
29307     68/push 0x11/imm32/alloc-id:fake:payload
29308     89/<- %ecx 4/r32/esp
29309 $test-emit-subx-function-call-with-literal-arg:initialize-var:
29310     # var var-foo/ecx: (payload var) = var(lit)
29311     68/push 0/imm32/no-register
29312     68/push 0/imm32/no-register
29313     68/push 0/imm32/no-stack-offset
29314     68/push 1/imm32/block-depth
29315     51/push-ecx/type
29316     68/push 0x11/imm32/alloc-id:fake
29317     68/push 0/imm32/name
29318     68/push 0/imm32/name
29319     68/push 0x11/imm32/alloc-id:fake:payload
29320     89/<- %ecx 4/r32/esp
29321 $test-emit-subx-function-call-with-literal-arg:initialize-var-name:
29322     # var-foo->name = "0x34"
29323     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
29324     (copy-array Heap "0x34" %eax)
29325 $test-emit-subx-function-call-with-literal-arg:initialize-stmt-var:
29326     # var operand/ebx: (payload stmt-var) = stmt-var(var-foo)
29327     68/push 0/imm32/is-deref:false
29328     68/push 0/imm32/next
29329     68/push 0/imm32/next
29330     51/push-ecx/var-foo
29331     68/push 0x11/imm32/alloc-id:fake
29332     68/push 0x11/imm32/alloc-id:fake:payload
29333     89/<- %ebx 4/r32/esp
29334 $test-emit-subx-function-call-with-literal-arg:initialize-stmt:
29335     # var stmt/esi: (addr statement)
29336     68/push 0/imm32/no-outputs
29337     68/push 0/imm32/no-outputs
29338     53/push-ebx/inouts
29339     68/push 0x11/imm32/alloc-id:fake
29340     68/push 0/imm32/operation
29341     68/push 0/imm32/operation
29342     68/push 1/imm32/tag
29343     89/<- %esi 4/r32/esp
29344 $test-emit-subx-function-call-with-literal-arg:initialize-stmt-operation:
29345     # stmt->operation = "f"
29346     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
29347     (copy-array Heap "f" %eax)
29348     # convert
29349     c7 0/subop/copy *Curr-block-depth 0/imm32
29350     (emit-subx-stmt _test-output-buffered-file %esi 0 %ebx Stderr 0)
29351     (flush _test-output-buffered-file)
29352 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
29358     # check output
29359     (check-next-stream-line-equal _test-output-stream "(f 0x34)" "F - test-emit-subx-stmt-function-call-with-literal-arg")
29360     # . epilogue
29361     89/<- %esp 5/r32/ebp
29362     5d/pop-to-ebp
29363     c3/return
29364 
29365 emit-indent:  # out: (addr buffered-file), n: int
29366     # . prologue
29367     55/push-ebp
29368     89/<- %ebp 4/r32/esp
29369     # . save registers
29370     50/push-eax
29371     # var i/eax: int = n
29372     8b/-> *(ebp+0xc) 0/r32/eax
29373     {
29374       # if (i <= 0) break
29375       3d/compare-eax-with 0/imm32
29376       7e/jump-if-<= break/disp8
29377       (write-buffered *(ebp+8) "  ")
29378       48/decrement-eax
29379       eb/jump loop/disp8
29380     }
29381 $emit-indent:end:
29382     # . restore registers
29383     58/pop-to-eax
29384     # . epilogue
29385     89/<- %esp 5/r32/ebp
29386     5d/pop-to-ebp
29387     c3/return
29388 
29389 emit-subx-prologue:  # out: (addr buffered-file)
29390     # . prologue
29391     55/push-ebp
29392     89/<- %ebp 4/r32/esp
29393     #
29394     (write-buffered *(ebp+8) "  # . prologue\n")
29395     (write-buffered *(ebp+8) "  55/push-ebp\n")
29396     (write-buffered *(ebp+8) "  89/<- %ebp 4/r32/esp\n")
29397 $emit-subx-prologue:end:
29398     # . epilogue
29399     89/<- %esp 5/r32/ebp
29400     5d/pop-to-ebp
29401     c3/return
29402 
29403 emit-subx-epilogue:  # out: (addr buffered-file)
29404     # . prologue
29405     55/push-ebp
29406     89/<- %ebp 4/r32/esp
29407     #
29408     (write-buffered *(ebp+8) "  # . epilogue\n")
29409     (write-buffered *(ebp+8) "  89/<- %esp 5/r32/ebp\n")
29410     (write-buffered *(ebp+8) "  5d/pop-to-ebp\n")
29411     (write-buffered *(ebp+8) "  c3/return\n")
29412 $emit-subx-epilogue:end:
29413     # . epilogue
29414     89/<- %esp 5/r32/ebp
29415     5d/pop-to-ebp
29416     c3/return