https://github.com/akkartik/mu/blob/main/linux/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 mu.subx
    6 #   $ ./a.elf < prog.mu > prog.elf
    7 
    8 # == Goals
    9 # 1. Be memory safe. It should be impossible to corrupt the heap, or to create
   10 # a bad pointer. (Requires strong type safety.)
   11 # 2. Do as little as possible to achieve goal 1. The translator should be
   12 # implementable in machine code.
   13 #   - minimize impedance mismatch between source language and SubX target
   14 #     (e.g. programmer manages registers manually)
   15 #   - checks over syntax
   16 #     (e.g. programmer's register allocation is checked)
   17 #   - runtime checks to avoid complex static analysis
   18 #     (e.g. array indexing always checks bounds)
   19 
   20 # == Language description
   21 # A program is a sequence of function and type definitions.
   22 #
   23 # Function example:
   24 #   fn foo n: int -> _/eax: int {
   25 #     ...
   26 #   }
   27 #
   28 # Functions consist of a name, optional inputs, optional outputs and a block.
   29 #
   30 # Function inputs and outputs are variables. All variables have a type and
   31 # storage specifier. They can be placed either in memory (on the stack) or in
   32 # one of 6 named registers.
   33 #   eax ecx edx ebx esi edi
   34 # Variables in registers must be primitive 32-bit types.
   35 # Variables not explicitly placed in a register are on the stack.
   36 #
   37 # Function inputs are always passed in memory (on the stack), while outputs
   38 # are always returned in registers. Outputs can't be named; they use the
   39 # dummy value '_'.
   40 #
   41 # Blocks mostly consist of statements.
   42 #
   43 # Statements mostly consist of a name, optional inputs and optional outputs.
   44 #
   45 # Statement inputs are variables or literals. Variables need to specify type
   46 # (and storage) the first time they're mentioned but not later.
   47 #
   48 # Statement outputs, like function outputs, must be variables in registers.
   49 #
   50 # Statement names must be either primitives or user-defined functions.
   51 #
   52 # Primitives can write to any register.
   53 # User-defined functions only write to hard-coded registers. Outputs of each
   54 # call must have the same registers as in the function definition.
   55 #
   56 # There are some other statement types:
   57 #   - blocks. Multiple statements surrounded by '{...}' and optionally
   58 #     prefixed with a label name and ':'
   59 #       - {
   60 #           ...
   61 #         }
   62 #       - foo: {
   63 #           ...
   64 #         }
   65 #
   66 #   - variable definitions on the stack. E.g.:
   67 #       - var foo: int
   68 #       - var bar: (array int 3)
   69 #     There's no initializer; variables are automatically initialized.
   70 #     The type of a local variable is either word-length (4 bytes) or starts with 'ref'.
   71 #
   72 #   - variables definitions in a register. E.g.:
   73 #       - var foo/eax: int <- add bar 1
   74 #     The initializer is mandatory and must be a valid instruction that writes
   75 #     a single output to the right register. In practice registers will
   76 #     usually be either initialized by primitives or copied from eax.
   77 #       - var eax: int <- foo bar quux
   78 #         var floo/ecx: int <- copy eax
   79 #
   80 # Still todo:
   81 #   global variables
   82 #   union types
   83 #
   84 # Formal types:
   85 #   A program is a linked list of functions
   86 #   A function contains:
   87 #     name: (handle array byte)
   88 #     inouts: linked list of vars  <-- 'inouts' is more precise than 'inputs'
   89 #       data: (handle var)
   90 #       next: (handle list)
   91 #     outputs: linked list of vars
   92 #       data: (handle var)
   93 #       next: (handle list)
   94 #     body: (handle block)
   95 #   A var-type contains:
   96 #     name: (handle array byte)
   97 #     type: (handle type-tree)
   98 #
   99 #   A statement can be:
  100 #     tag 0: a block
  101 #     tag 1: a simple statement (stmt1)
  102 #     tag 2: a variable defined on the stack
  103 #     tag 3: a variable defined in a register
  104 #
  105 #   A block contains:
  106 #     tag: 0
  107 #     statements: (handle list stmt)
  108 #     name: (handle array byte) -- starting with '$'
  109 #
  110 #   A regular statement contains:
  111 #     tag: 1
  112 #     operation: (handle array byte)
  113 #     inouts: (handle list operand)
  114 #     outputs: (handle list var)
  115 #
  116 #   A variable defined on the stack contains:
  117 #     tag: 2
  118 #     name: (handle array byte)
  119 #     type: (handle type-tree)
  120 #
  121 #   A variable defined in a register contains:
  122 #     tag: 3
  123 #     name: (handle array byte)
  124 #     type: (handle type-tree)
  125 #     reg: (handle array byte)
  126 
  127 # == Translation: managing the stack
  128 # Now that we know what the language looks like in the large, let's think
  129 # about how translation happens from the bottom up. One crucial piece of the
  130 # puzzle is how Mu will clean up variables defined on the stack for you.
  131 #
  132 # Assume that we maintain a 'functions' list while parsing source code. And a
  133 # 'primitives' list is a global constant. Both these contain enough information
  134 # to perform type-checking on function calls or primitive statements, respectively.
  135 #
  136 # Defining variables pushes them on a stack with the current block depth and
  137 # enough information about their location (stack offset or register).
  138 # Starting a block increments the current block id.
  139 # Each statement now has enough information to emit code for it.
  140 # Ending a block is where the magic happens:
  141 #   pop all variables at the current block depth
  142 #   emit code to restore all register variables introduced at the current depth
  143 #   emit code to clean up all stack variables at the current depth (just increment esp)
  144 #   decrement the current block depth
  145 #
  146 # Formal types:
  147 #   live-vars: stack of vars
  148 #   var:
  149 #     name: (handle array byte)
  150 #     type: (handle type-tree)
  151 #     block: int
  152 #     stack-offset: int  (added to ebp)
  153 #     register: (handle array byte)
  154 #       either usual register names
  155 #       or '*' to indicate any register
  156 #   At most one of stack-offset or register-index must be non-zero.
  157 #   A register of '*' designates a variable _template_. Only legal in formal
  158 #   parameters for primitives.
  159 
  160 # == Translating a single function call
  161 # This one's easy. Assuming we've already checked things, we just drop the
  162 # outputs (which use hard-coded registers) and emit inputs in a standard format.
  163 #
  164 # out1, out2, out3, ... <- name inout1, inout2, inout3, ...
  165 # =>
  166 # (name inout1 inout2 inout3)
  167 #
  168 # Formal types:
  169 #   functions: linked list of info
  170 #     name: (handle array byte)
  171 #     inouts: linked list of vars
  172 #     outputs: linked list of vars
  173 #     body: block (linked list of statements)
  174 
  175 # == Translating a single primitive instruction
  176 # A second crucial piece of the puzzle is how Mu converts fairly regular
  177 # primitives with their uniform syntax to SubX instructions with their gnarly
  178 # x86 details.
  179 #
  180 # Mu instructions have inputs and outputs. Primitives can have up to 2 of
  181 # them.
  182 # SubX instructions have rm32 and r32 operands.
  183 # The translation between them covers almost all the possibilities.
  184 #   Instructions with 1 inout may turn into ones with 1 rm32
  185 #     (e.g. incrementing a var on the stack)
  186 #   Instructions with 1 output may turn into ones with 1 rm32
  187 #     (e.g. incrementing a var in a register)
  188 #   1 inout and 1 output may turn into 1 rm32 and 1 r32
  189 #     (e.g. adding a var to a reg)
  190 #   2 inouts may turn into 1 rm32 and 1 r32
  191 #     (e.g. adding a reg to a var)
  192 #   1 inout and 1 literal may turn into 1 rm32 and 1 imm32
  193 #     (e.g. adding a constant to a var)
  194 #   1 output and 1 literal may turn into 1 rm32 and 1 imm32
  195 #     (e.g. adding a constant to a reg)
  196 #   2 outputs to hardcoded registers and 1 inout may turn into 1 rm32
  197 #     (special-case: divide edx:eax by a var or reg)
  198 # Observations:
  199 #   We always emit rm32. It may be the first inout or the first output.
  200 #   We may emit r32 or imm32 or neither.
  201 #   When we emit r32 it may come from first inout or second inout or first output.
  202 #
  203 # Accordingly, the formal data structure for a primitive looks like this:
  204 #   primitives: linked list of info
  205 #     name: (handle array byte)
  206 #     mu-inouts: linked list of vars to check
  207 #     mu-outputs: linked list of vars to check; at most a singleton
  208 #     subx-name: (handle array byte)
  209 #     subx-rm32: enum arg-location
  210 #     subx-r32: enum arg-location
  211 #     subx-imm32: enum arg-location
  212 #     subx-imm8: enum arg-location
  213 #     subx-disp32: enum arg-location
  214 #     subx-xm32: enum arg-location
  215 #     subx-x32: enum arg-location
  216 #   arg-location: enum
  217 #     0 means none
  218 #     1 means first inout
  219 #     2 means second inout
  220 #     3 means first output
  221 
  222 # == Translating a block
  223 # Emit block name if necessary
  224 # Emit '{'
  225 # When you encounter a statement, emit it as above
  226 # When you encounter a variable declaration
  227 #   emit any code needed for it (bzeros)
  228 #   push it on the var stack
  229 #   update register dict if necessary
  230 # When you encounter '}'
  231 #   While popping variables off the var stack until block id changes
  232 #     Emit code needed to clean up the stack
  233 #       either increment esp
  234 #       or pop into appropriate register
  235 
  236 # The rest is straightforward.
  237 
  238 == data
  239 
  240 Program:
  241 _Program-functions:  # (handle function)
  242   0/imm32
  243 _Program-functions->payload:
  244   0/imm32
  245 _Program-types:  # (handle typeinfo)
  246   0/imm32
  247 _Program-types->payload:
  248   0/imm32
  249 _Program-signatures:  # (handle function)
  250   0/imm32
  251 _Program-signatures->payload:
  252   0/imm32
  253 
  254 # Some constants for simulating the data structures described above.
  255 # Many constants here come with a type in a comment.
  256 #
  257 # Sometimes the type is of the value at that offset for the given type. For
  258 # example, if you start at a function record and move forward Function-inouts
  259 # bytes, you'll find a (handle list var).
  260 #
  261 # At other times, the type is of the constant itself. For example, the type of
  262 # the constant Function-size is (addr int). To get the size of a function,
  263 # look in *Function-size.
  264 
  265 Function-name:  # (handle array byte)
  266   0/imm32
  267 Function-inouts:  # (handle list var)
  268   8/imm32
  269 Function-outputs:  # (handle list var)
  270   0x10/imm32
  271 Function-body:  # (handle block)
  272   0x18/imm32
  273 Function-next:  # (handle function)
  274   0x20/imm32
  275 Function-size:  # (addr int)
  276   0x28/imm32/40
  277 
  278 Primitive-name:  # (handle array byte)
  279   0/imm32
  280 Primitive-inouts:  # (handle list var)
  281   8/imm32
  282 Primitive-outputs:  # (handle list var)
  283   0x10/imm32
  284 Primitive-subx-name:  # (handle array byte)
  285   0x18/imm32
  286 Primitive-subx-rm32:  # enum arg-location
  287   0x20/imm32
  288 Primitive-subx-r32:  # enum arg-location
  289   0x24/imm32
  290 Primitive-subx-imm32:  # enum arg-location
  291   0x28/imm32
  292 Primitive-subx-imm8:  # enum arg-location  -- only for bit shifts
  293   0x2c/imm32
  294 Primitive-subx-disp32:  # enum arg-location  -- only for branches
  295   0x30/imm32
  296 Primitive-subx-xm32:  # enum arg-location
  297   0x34/imm32
  298 Primitive-subx-x32:  # enum arg-location
  299   0x38/imm32
  300 Primitive-next:  # (handle function)
  301   0x3c/imm32
  302 Primitive-size:  # (addr int)
  303   0x44/imm32/68
  304 
  305 Stmt-tag:  # int
  306   0/imm32
  307 
  308 Block-stmts:  # (handle list stmt)
  309   4/imm32
  310 Block-var:  # (handle var)
  311   0xc/imm32
  312 
  313 Stmt1-operation:  # (handle array byte)
  314   4/imm32
  315 Stmt1-inouts:  # (handle stmt-var)
  316   0xc/imm32
  317 Stmt1-outputs:  # (handle stmt-var)
  318   0x14/imm32
  319 
  320 Vardef-var:  # (handle var)
  321   4/imm32
  322 
  323 Regvardef-operation:  # (handle array byte)
  324   4/imm32
  325 Regvardef-inouts:  # (handle stmt-var)
  326   0xc/imm32
  327 Regvardef-outputs:  # (handle stmt-var)  # will have exactly one element
  328   0x14/imm32
  329 
  330 Stmt-size:  # (addr int)
  331   0x1c/imm32
  332 
  333 Var-name:  # (handle array byte)
  334   0/imm32
  335 Var-type:  # (handle type-tree)
  336   8/imm32
  337 Var-block-depth:  # int -- not available until code-generation time
  338   0x10/imm32
  339 Var-offset:  # int -- not available until code-generation time
  340   0x14/imm32
  341 Var-register:  # (handle array byte) -- name of a register
  342   0x18/imm32
  343 Var-size:  # (addr int)
  344   0x20/imm32
  345 
  346 List-value:  # (handle _)
  347   0/imm32
  348 List-next:  # (handle list _)
  349   8/imm32
  350 List-size:  # (addr int)
  351   0x10/imm32
  352 
  353 # A stmt-var is like a list of vars with call-site specific metadata
  354 Stmt-var-value:  # (handle var)
  355   0/imm32
  356 Stmt-var-next:  # (handle stmt-var)
  357   8/imm32
  358 Stmt-var-is-deref:  # boolean
  359   0x10/imm32
  360 Stmt-var-size:  # (addr int)
  361   0x14/imm32
  362 
  363 # A live-var is a var augmented with information needed for tracking live
  364 # variables.
  365 Live-var-value:  # (handle var)
  366   0/imm32
  367 Live-var-register-spilled:  # boolean; only used if value is in a register, and only during code-gen
  368   8/imm32
  369 Live-var-size:  # (addr int)
  370   0xc/imm32
  371 
  372 # Types are expressed as trees (s-expressions) of type-ids (ints).
  373 
  374 Type-tree-is-atom:  # boolean
  375   0/imm32
  376 # if is-atom?
  377 Type-tree-value:  # type-id
  378   4/imm32
  379 Type-tree-value-size:  # int (for static data structure sizes)
  380   8/imm32
  381 Type-tree-parameter-name:  # (handle array byte) for type parameters
  382   8/imm32
  383 # unless is-atom?
  384 Type-tree-left:  # (addr type-tree)
  385   4/imm32
  386 Type-tree-right:  # (addr type-tree)
  387   0xc/imm32
  388 #
  389 Type-tree-size:  # (addr int)
  390   0x14/imm32
  391 
  392 # Types
  393 
  394 # TODO: Turn this data structure into valid Mu, with (fake) handles rather than addrs.
  395 Type-id:  # (stream (addr array byte))
  396   0/imm32/write  # initialized later from Primitive-type-ids
  397   0/imm32/read
  398   0x100/imm32/size
  399   # data
  400   0/imm32  # 0 reserved for literals; value is just the name
  401            # Not to be used directly, so we don't include a name here.
  402   "int"/imm32  # 1
  403   "addr"/imm32  # 2
  404   "array"/imm32  # 3
  405   "handle"/imm32  # 4
  406   "boolean"/imm32  # 5
  407   0/imm32  # 6 reserved for constants; they're like literals, but value is an int in Var-offset
  408            # Not to be used directly, so we don't include a name here.
  409   "offset"/imm32  # 7: (offset T) is guaranteed to be a 32-bit multiple of size-of(T)
  410   # 0x20
  411   "byte"/imm32  # 8
  412   0/imm32  # 9 reserved for array-capacity; value is in Type-tree-size.
  413            # Not to be used directly, so we don't include a name here.
  414   0/imm32  # 10 reserved for type parameters; value is (address array byte) in Type-tree-value2.
  415            # Not to be used directly, so we don't include a name here.
  416   "stream"/imm32  # 11
  417   "slice"/imm32  # 12
  418   "code-point"/imm32  # 13; smallest scannable unit from a text stream
  419   "grapheme"/imm32  # 14; smallest printable unit; will eventually be composed of multiple code-points, but currently corresponds 1:1
  420                     # only 4-byte graphemes in utf-8 are currently supported;
  421                     # unclear how we should deal with larger clusters.
  422   "float"/imm32     # 15
  423   # 0x40
  424   0/imm32  # 16 reserved for literal strings; value is just the name
  425            # Not to be used directly, so we don't include a name here.
  426            # TODO: move this up next to literal ints
  427   # Keep Primitive-type-ids in sync if you add types here.
  428           0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  429   0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  430   0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  431   0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  432   0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  433   0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  434 
  435 Primitive-type-ids:  # (addr int)
  436   0x44
  437 
  438 # == Type definitions
  439 # Program->types contains some typeinfo for each type definition.
  440 # Types contain vars with types, but can't specify registers.
  441 Typeinfo-id:  # type-id
  442   0/imm32
  443 Typeinfo-fields:  # (handle table (handle array byte) (handle typeinfo-entry))
  444   4/imm32
  445 # Total size must be >= 0
  446 # During parsing it may take on two additional values:
  447 #   -2: not yet initialized
  448 #   -1: in process of being computed
  449 # See populate-mu-type-sizes for details.
  450 Typeinfo-total-size-in-bytes:  # int
  451   0xc/imm32
  452 Typeinfo-next:  # (handle typeinfo)
  453   0x10/imm32
  454 Typeinfo-size:  # (addr int)
  455   0x18/imm32
  456 
  457 # Each entry in the typeinfo->fields table has a pointer to a string and a
  458 # pointer to a typeinfo-entry.
  459 Typeinfo-fields-row-size:  # (addr int)
  460   0x10/imm32
  461 
  462 # typeinfo-entry objects have information about a field in a single record type
  463 #
  464 # each field of a type is represented using two var's:
  465 #   1. the input var: expected type of the field; convenient for creating using parse-var-with-type
  466 #   2. the output var: a constant containing the byte offset; convenient for code-generation
  467 # computing the output happens after parsing; in the meantime we preserve the
  468 # order of fields in the 'index' field.
  469 Typeinfo-entry-input-var:  # (handle var)
  470   0/imm32
  471 Typeinfo-entry-index:  # int
  472   8/imm32
  473 Typeinfo-entry-output-var:  # (handle var)
  474   0xc/imm32
  475 Typeinfo-entry-size:  # (addr int)
  476   0x14/imm32
  477 
  478 == code
  479 
  480 Entry:
  481     # . prologue
  482     89/<- %ebp 4/r32/esp
  483     (new-segment *Heap-size Heap)
  484 #?     (test-address-with-right-type-for-stream)
  485     # if (argv[1] == "test') run-tests()
  486     {
  487       # if (argc <= 1) break
  488       81 7/subop/compare *ebp 1/imm32
  489       7e/jump-if-<= break/disp8
  490       # if (argv[1] != "test") break
  491       (kernel-string-equal? *(ebp+8) "test")  # => eax
  492       3d/compare-eax-and 0/imm32/false
  493       74/jump-if-= break/disp8
  494       #
  495       (run-tests)
  496       # syscall(exit, *Num-test-failures)
  497       8b/-> *Num-test-failures 3/r32/ebx
  498       eb/jump $mu-main:end/disp8
  499     }
  500     # otherwise convert Stdin
  501     (write-buffered Stdout "== code\n")
  502     (convert-mu Stdin Stdout Stderr 0)
  503     (flush Stdout)
  504     # syscall(exit, 0)
  505     bb/copy-to-ebx 0/imm32
  506 $mu-main:end:
  507     e8/call syscall_exit/disp32
  508 
  509 convert-mu:  # in: (addr buffered-file), out: (addr buffered-file), err: (addr buffered-file), ed: (addr exit-descriptor)
  510     # . prologue
  511     55/push-ebp
  512     89/<- %ebp 4/r32/esp
  513     # . save registers
  514     50/push-eax
  515     # initialize global data structures
  516     c7 0/subop/copy *Next-block-index 1/imm32
  517     8b/-> *Primitive-type-ids 0/r32/eax
  518     89/<- *Type-id 0/r32/eax  # stream-write
  519     c7 0/subop/copy *_Program-functions 0/imm32
  520     c7 0/subop/copy *_Program-functions->payload 0/imm32
  521     c7 0/subop/copy *_Program-types 0/imm32
  522     c7 0/subop/copy *_Program-types->payload 0/imm32
  523     c7 0/subop/copy *_Program-signatures 0/imm32
  524     c7 0/subop/copy *_Program-signatures->payload 0/imm32
  525     #
  526     (parse-mu *(ebp+8) *(ebp+0x10) *(ebp+0x14))
  527     (populate-mu-type-sizes *(ebp+0x10) *(ebp+0x14))
  528 #?     (dump-typeinfos "=== typeinfos\n")
  529     (check-mu-types *(ebp+0x10) *(ebp+0x14))
  530     (emit-subx *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
  531 $convert-mu:end:
  532     # . restore registers
  533     58/pop-to-eax
  534     # . epilogue
  535     89/<- %esp 5/r32/ebp
  536     5d/pop-to-ebp
  537     c3/return
  538 
  539 test-convert-empty-input:
  540     # empty input => empty output
  541     # . prologue
  542     55/push-ebp
  543     89/<- %ebp 4/r32/esp
  544     # setup
  545     (clear-stream _test-input-stream)
  546     (clear-stream $_test-input-buffered-file->buffer)
  547     (clear-stream _test-output-stream)
  548     (clear-stream $_test-output-buffered-file->buffer)
  549     #
  550     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  551     (flush _test-output-buffered-file)
  552     (check-stream-equal _test-output-stream "" "F - test-convert-empty-input")
  553     # . epilogue
  554     89/<- %esp 5/r32/ebp
  555     5d/pop-to-ebp
  556     c3/return
  557 
  558 test-convert-function-skeleton:
  559     # . prologue
  560     55/push-ebp
  561     89/<- %ebp 4/r32/esp
  562     # setup
  563     (clear-stream _test-input-stream)
  564     (clear-stream $_test-input-buffered-file->buffer)
  565     (clear-stream _test-output-stream)
  566     (clear-stream $_test-output-buffered-file->buffer)
  567     #
  568     (write _test-input-stream "fn foo {\n")
  569     (write _test-input-stream "}\n")
  570     # convert
  571     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  572     (flush _test-output-buffered-file)
  573 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
  579     # check output
  580     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-skeleton/0")
  581     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-skeleton/1")
  582     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-skeleton/2")
  583     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-skeleton/3")
  584     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-skeleton/4")
  585     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-skeleton/5")
  586     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-skeleton/6")
  587     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-skeleton/7")
  588     # . epilogue
  589     89/<- %esp 5/r32/ebp
  590     5d/pop-to-ebp
  591     c3/return
  592 
  593 test-convert-multiple-function-skeletons:
  594     # . prologue
  595     55/push-ebp
  596     89/<- %ebp 4/r32/esp
  597     # setup
  598     (clear-stream _test-input-stream)
  599     (clear-stream $_test-input-buffered-file->buffer)
  600     (clear-stream _test-output-stream)
  601     (clear-stream $_test-output-buffered-file->buffer)
  602     #
  603     (write _test-input-stream "fn foo {\n")
  604     (write _test-input-stream "}\n")
  605     (write _test-input-stream "fn bar {\n")
  606     (write _test-input-stream "}\n")
  607     # convert
  608     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  609     (flush _test-output-buffered-file)
  610 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
  616     # check first function
  617     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-multiple-function-skeletons/0")
  618     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-multiple-function-skeletons/1")
  619     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-multiple-function-skeletons/2")
  620     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-multiple-function-skeletons/3")
  621     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-multiple-function-skeletons/4")
  622     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-multiple-function-skeletons/5")
  623     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-multiple-function-skeletons/6")
  624     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-multiple-function-skeletons/7")
  625     # check second function
  626     (check-next-stream-line-equal _test-output-stream "bar:"                    "F - test-convert-multiple-function-skeletons/10")
  627     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-multiple-function-skeletons/11")
  628     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-multiple-function-skeletons/12")
  629     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-multiple-function-skeletons/13")
  630     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-multiple-function-skeletons/14")
  631     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-multiple-function-skeletons/15")
  632     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-multiple-function-skeletons/16")
  633     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-multiple-function-skeletons/17")
  634     # . epilogue
  635     89/<- %esp 5/r32/ebp
  636     5d/pop-to-ebp
  637     c3/return
  638 
  639 test-convert-function-with-arg:
  640     # . prologue
  641     55/push-ebp
  642     89/<- %ebp 4/r32/esp
  643     # setup
  644     (clear-stream _test-input-stream)
  645     (clear-stream $_test-input-buffered-file->buffer)
  646     (clear-stream _test-output-stream)
  647     (clear-stream $_test-output-buffered-file->buffer)
  648     #
  649     (write _test-input-stream "fn foo n: int {\n")
  650     (write _test-input-stream "}\n")
  651     # convert
  652     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  653     (flush _test-output-buffered-file)
  654 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
  660     # check output
  661     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-arg/0")
  662     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-arg/1")
  663     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-arg/2")
  664     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-arg/3")
  665     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-arg/4")
  666     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-arg/5")
  667     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-arg/6")
  668     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-arg/7")
  669     # . epilogue
  670     89/<- %esp 5/r32/ebp
  671     5d/pop-to-ebp
  672     c3/return
  673 
  674 test-function-with-redefined-name:
  675     # . prologue
  676     55/push-ebp
  677     89/<- %ebp 4/r32/esp
  678     # setup
  679     (clear-stream _test-input-stream)
  680     (clear-stream $_test-input-buffered-file->buffer)
  681     (clear-stream _test-output-stream)
  682     (clear-stream $_test-output-buffered-file->buffer)
  683     (clear-stream _test-error-stream)
  684     (clear-stream $_test-error-buffered-file->buffer)
  685     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  686     68/push 0/imm32
  687     68/push 0/imm32
  688     89/<- %edx 4/r32/esp
  689     (tailor-exit-descriptor %edx 0x10)
  690     #
  691     (write _test-input-stream "fn foo {\n")
  692     (write _test-input-stream "}\n")
  693     (write _test-input-stream "fn foo {\n")
  694     (write _test-input-stream "}\n")
  695     # convert
  696     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  697     # registers except esp clobbered at this point
  698     # restore ed
  699     89/<- %edx 4/r32/esp
  700     (flush _test-output-buffered-file)
  701     (flush _test-error-buffered-file)
  702 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
  708     # check output
  709     (check-stream-equal _test-output-stream  ""  "F - test-function-with-redefined-name: output should be empty")
  710     (check-next-stream-line-equal _test-error-stream  "fn foo defined more than once"  "F - test-function-with-redefined-name: error message")
  711     # check that stop(1) was called
  712     (check-ints-equal *(edx+4) 2 "F - test-function-with-redefined-name: exit status")
  713     # don't restore from ebp
  714     81 0/subop/add %esp 8/imm32
  715     # . epilogue
  716     5d/pop-to-ebp
  717     c3/return
  718 
  719 test-function-with-redefined-name-2:
  720     # . prologue
  721     55/push-ebp
  722     89/<- %ebp 4/r32/esp
  723     # setup
  724     (clear-stream _test-input-stream)
  725     (clear-stream $_test-input-buffered-file->buffer)
  726     (clear-stream _test-output-stream)
  727     (clear-stream $_test-output-buffered-file->buffer)
  728     (clear-stream _test-error-stream)
  729     (clear-stream $_test-error-buffered-file->buffer)
  730     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  731     68/push 0/imm32
  732     68/push 0/imm32
  733     89/<- %edx 4/r32/esp
  734     (tailor-exit-descriptor %edx 0x10)
  735     #
  736     (write _test-input-stream "fn foo {\n")
  737     (write _test-input-stream "}\n")
  738     (write _test-input-stream "sig foo\n")
  739     # convert
  740     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  741     # registers except esp clobbered at this point
  742     # restore ed
  743     89/<- %edx 4/r32/esp
  744     (flush _test-output-buffered-file)
  745     (flush _test-error-buffered-file)
  746 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
  752     # check output
  753     (check-stream-equal _test-output-stream  ""  "F - test-function-with-redefined-name-2: output should be empty")
  754     (check-next-stream-line-equal _test-error-stream  "fn foo defined more than once"  "F - test-function-with-redefined-name-2: error message")
  755     # check that stop(1) was called
  756     (check-ints-equal *(edx+4) 2 "F - test-function-with-redefined-name-2: exit status")
  757     # don't restore from ebp
  758     81 0/subop/add %esp 8/imm32
  759     # . epilogue
  760     5d/pop-to-ebp
  761     c3/return
  762 
  763 test-function-with-redefined-name-3:
  764     # . prologue
  765     55/push-ebp
  766     89/<- %ebp 4/r32/esp
  767     # setup
  768     (clear-stream _test-input-stream)
  769     (clear-stream $_test-input-buffered-file->buffer)
  770     (clear-stream _test-output-stream)
  771     (clear-stream $_test-output-buffered-file->buffer)
  772     (clear-stream _test-error-stream)
  773     (clear-stream $_test-error-buffered-file->buffer)
  774     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  775     68/push 0/imm32
  776     68/push 0/imm32
  777     89/<- %edx 4/r32/esp
  778     (tailor-exit-descriptor %edx 0x10)
  779     #
  780     (write _test-input-stream "sig foo\n")
  781     (write _test-input-stream "fn foo {\n")
  782     (write _test-input-stream "}\n")
  783     # convert
  784     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  785     # registers except esp clobbered at this point
  786     # restore ed
  787     89/<- %edx 4/r32/esp
  788     (flush _test-output-buffered-file)
  789     (flush _test-error-buffered-file)
  790 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
  796     # check output
  797     (check-stream-equal _test-output-stream  ""  "F - test-function-with-redefined-name-3: output should be empty")
  798     (check-next-stream-line-equal _test-error-stream  "fn foo defined more than once"  "F - test-function-with-redefined-name-3: error message")
  799     # check that stop(1) was called
  800     (check-ints-equal *(edx+4) 2 "F - test-function-with-redefined-name-3: exit status")
  801     # don't restore from ebp
  802     81 0/subop/add %esp 8/imm32
  803     # . epilogue
  804     5d/pop-to-ebp
  805     c3/return
  806 
  807 test-function-with-inout-in-register:
  808     # . prologue
  809     55/push-ebp
  810     89/<- %ebp 4/r32/esp
  811     # setup
  812     (clear-stream _test-input-stream)
  813     (clear-stream $_test-input-buffered-file->buffer)
  814     (clear-stream _test-output-stream)
  815     (clear-stream $_test-output-buffered-file->buffer)
  816     (clear-stream _test-error-stream)
  817     (clear-stream $_test-error-buffered-file->buffer)
  818     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  819     68/push 0/imm32
  820     68/push 0/imm32
  821     89/<- %edx 4/r32/esp
  822     (tailor-exit-descriptor %edx 0x10)
  823     #
  824     (write _test-input-stream "fn foo x/eax: int {\n")
  825     (write _test-input-stream "}\n")
  826     # convert
  827     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  828     # registers except esp clobbered at this point
  829     # restore ed
  830     89/<- %edx 4/r32/esp
  831     (flush _test-output-buffered-file)
  832     (flush _test-error-buffered-file)
  833 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
  839     # check output
  840     (check-stream-equal _test-output-stream  ""  "F - test-function-with-inout-in-register: output should be empty")
  841     (check-next-stream-line-equal _test-error-stream  "fn foo: function inout 'x' cannot be in a register"  "F - test-function-with-inout-in-register: error message")
  842     # check that stop(1) was called
  843     (check-ints-equal *(edx+4) 2 "F - test-function-with-inout-in-register: exit status")
  844     # don't restore from ebp
  845     81 0/subop/add %esp 8/imm32
  846     # . epilogue
  847     5d/pop-to-ebp
  848     c3/return
  849 
  850 test-function-with-addr-output:
  851     # . prologue
  852     55/push-ebp
  853     89/<- %ebp 4/r32/esp
  854     # setup
  855     (clear-stream _test-input-stream)
  856     (clear-stream $_test-input-buffered-file->buffer)
  857     (clear-stream _test-output-stream)
  858     (clear-stream $_test-output-buffered-file->buffer)
  859     (clear-stream _test-error-stream)
  860     (clear-stream $_test-error-buffered-file->buffer)
  861     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  862     68/push 0/imm32
  863     68/push 0/imm32
  864     89/<- %edx 4/r32/esp
  865     (tailor-exit-descriptor %edx 0x10)
  866     #
  867     (write _test-input-stream "fn foo -> _/eax: (addr int) {\n")
  868     (write _test-input-stream "}\n")
  869     # convert
  870     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  871     # registers except esp clobbered at this point
  872     # restore ed
  873     89/<- %edx 4/r32/esp
  874     (flush _test-output-buffered-file)
  875     (flush _test-error-buffered-file)
  876 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
  882     # check output
  883     (check-stream-equal _test-output-stream  ""  "F - test-function-with-addr-output: output should be empty")
  884     (check-next-stream-line-equal _test-error-stream  "fn foo: output cannot have an addr type; that could allow unsafe addresses to escape the function"  "F - test-function-with-addr-output: error message")
  885     # check that stop(1) was called
  886     (check-ints-equal *(edx+4) 2 "F - test-function-with-addr-output: exit status")
  887     # don't restore from ebp
  888     81 0/subop/add %esp 8/imm32
  889     # . epilogue
  890     5d/pop-to-ebp
  891     c3/return
  892 
  893 test-function-with-addr-inout:
  894     # . prologue
  895     55/push-ebp
  896     89/<- %ebp 4/r32/esp
  897     # setup
  898     (clear-stream _test-input-stream)
  899     (clear-stream $_test-input-buffered-file->buffer)
  900     (clear-stream _test-output-stream)
  901     (clear-stream $_test-output-buffered-file->buffer)
  902     (clear-stream _test-error-stream)
  903     (clear-stream $_test-error-buffered-file->buffer)
  904     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  905     68/push 0/imm32
  906     68/push 0/imm32
  907     89/<- %edx 4/r32/esp
  908     (tailor-exit-descriptor %edx 0x10)
  909     #
  910     (write _test-input-stream "fn foo a: (addr addr int) {\n")
  911     (write _test-input-stream "}\n")
  912     # convert
  913     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  914     # registers except esp clobbered at this point
  915     # restore ed
  916     89/<- %edx 4/r32/esp
  917     (flush _test-output-buffered-file)
  918     (flush _test-error-buffered-file)
  919 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
  925     # check output
  926     (check-stream-equal _test-output-stream  ""  "F - test-function-with-addr-inout: output should be empty")
  927     (check-next-stream-line-equal _test-error-stream  "fn foo: inout 'a' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function"  "F - test-function-with-addr-inout: error message")
  928     # check that stop(1) was called
  929     (check-ints-equal *(edx+4) 2 "F - test-function-with-addr-inout: exit status")
  930     # don't restore from ebp
  931     81 0/subop/add %esp 8/imm32
  932     # . epilogue
  933     5d/pop-to-ebp
  934     c3/return
  935 
  936 test-function-with-addr-inout-2:
  937     # . prologue
  938     55/push-ebp
  939     89/<- %ebp 4/r32/esp
  940     # setup
  941     (clear-stream _test-input-stream)
  942     (clear-stream $_test-input-buffered-file->buffer)
  943     (clear-stream _test-output-stream)
  944     (clear-stream $_test-output-buffered-file->buffer)
  945     (clear-stream _test-error-stream)
  946     (clear-stream $_test-error-buffered-file->buffer)
  947     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  948     68/push 0/imm32
  949     68/push 0/imm32
  950     89/<- %edx 4/r32/esp
  951     (tailor-exit-descriptor %edx 0x10)
  952     #
  953     (write _test-input-stream "fn foo a: (addr array addr int) {\n")
  954     (write _test-input-stream "}\n")
  955     # convert
  956     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  957     # registers except esp clobbered at this point
  958     # restore ed
  959     89/<- %edx 4/r32/esp
  960     (flush _test-output-buffered-file)
  961     (flush _test-error-buffered-file)
  962 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
  968     # check output
  969     (check-stream-equal _test-output-stream  ""  "F - test-function-with-addr-inout-2: output should be empty")
  970     (check-next-stream-line-equal _test-error-stream  "fn foo: inout 'a' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function"  "F - test-function-with-addr-inout-2: error message")
  971     # check that stop(1) was called
  972     (check-ints-equal *(edx+4) 2 "F - test-function-with-addr-inout-2: exit status")
  973     # don't restore from ebp
  974     81 0/subop/add %esp 8/imm32
  975     # . epilogue
  976     5d/pop-to-ebp
  977     c3/return
  978 
  979 test-function-with-addr-inout-3:
  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     (clear-stream _test-error-stream)
  989     (clear-stream $_test-error-buffered-file->buffer)
  990     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  991     68/push 0/imm32
  992     68/push 0/imm32
  993     89/<- %edx 4/r32/esp
  994     (tailor-exit-descriptor %edx 0x10)
  995     #
  996     (write _test-input-stream "fn foo a: (addr array (addr int) 3) {\n")
  997     (write _test-input-stream "}\n")
  998     # convert
  999     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1000     # registers except esp clobbered at this point
 1001     # restore ed
 1002     89/<- %edx 4/r32/esp
 1003     (flush _test-output-buffered-file)
 1004     (flush _test-error-buffered-file)
 1005 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1011     # check output
 1012     (check-stream-equal _test-output-stream  ""  "F - test-function-with-addr-inout-3: output should be empty")
 1013     (check-next-stream-line-equal _test-error-stream  "fn foo: inout 'a' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function"  "F - test-function-with-addr-inout-3: error message")
 1014     # check that stop(1) was called
 1015     (check-ints-equal *(edx+4) 2 "F - test-function-with-addr-inout-3: exit status")
 1016     # don't restore from ebp
 1017     81 0/subop/add %esp 8/imm32
 1018     # . epilogue
 1019     5d/pop-to-ebp
 1020     c3/return
 1021 
 1022 test-function-with-addr-inout-4:
 1023     # . prologue
 1024     55/push-ebp
 1025     89/<- %ebp 4/r32/esp
 1026     # setup
 1027     (clear-stream _test-input-stream)
 1028     (clear-stream $_test-input-buffered-file->buffer)
 1029     (clear-stream _test-output-stream)
 1030     (clear-stream $_test-output-buffered-file->buffer)
 1031     (clear-stream _test-error-stream)
 1032     (clear-stream $_test-error-buffered-file->buffer)
 1033     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1034     68/push 0/imm32
 1035     68/push 0/imm32
 1036     89/<- %edx 4/r32/esp
 1037     (tailor-exit-descriptor %edx 0x10)
 1038     #
 1039     (write _test-input-stream "fn foo a: (array (addr int) 3) {\n")
 1040     (write _test-input-stream "}\n")
 1041     # convert
 1042     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1043     # registers except esp clobbered at this point
 1044     # restore ed
 1045     89/<- %edx 4/r32/esp
 1046     (flush _test-output-buffered-file)
 1047     (flush _test-error-buffered-file)
 1048 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1054     # check output
 1055     (check-stream-equal _test-output-stream  ""  "F - test-function-with-addr-inout-4: output should be empty")
 1056     (check-next-stream-line-equal _test-error-stream  "fn foo: inout 'a' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function"  "F - test-function-with-addr-inout-4: error message")
 1057     # check that stop(1) was called
 1058     (check-ints-equal *(edx+4) 2 "F - test-function-with-addr-inout-4: exit status")
 1059     # don't restore from ebp
 1060     81 0/subop/add %esp 8/imm32
 1061     # . epilogue
 1062     5d/pop-to-ebp
 1063     c3/return
 1064 
 1065 # 'main' is an exception
 1066 test-function-main-with-addr-inout:
 1067     # . prologue
 1068     55/push-ebp
 1069     89/<- %ebp 4/r32/esp
 1070     # setup
 1071     (clear-stream _test-input-stream)
 1072     (clear-stream $_test-input-buffered-file->buffer)
 1073     (clear-stream _test-output-stream)
 1074     (clear-stream $_test-output-buffered-file->buffer)
 1075     #
 1076     (write _test-input-stream "fn main a: (addr addr int) {\n")
 1077     (write _test-input-stream "}\n")
 1078     # convert
 1079     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1080     (flush _test-output-buffered-file)
 1081     # no errors
 1082     # . epilogue
 1083     89/<- %esp 5/r32/ebp
 1084     5d/pop-to-ebp
 1085     c3/return
 1086 
 1087 # 'lookup' is an exception, but only in signatures
 1088 test-signature-lookup-with-addr-inout:
 1089     # . prologue
 1090     55/push-ebp
 1091     89/<- %ebp 4/r32/esp
 1092     # setup
 1093     (clear-stream _test-input-stream)
 1094     (clear-stream $_test-input-buffered-file->buffer)
 1095     (clear-stream _test-output-stream)
 1096     (clear-stream $_test-output-buffered-file->buffer)
 1097     #
 1098     (write _test-input-stream "sig lookup h: (handle _T) -> _/eax: (addr _T)\n")
 1099     # convert
 1100     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1101     (flush _test-output-buffered-file)
 1102     # no errors
 1103     # . epilogue
 1104     89/<- %esp 5/r32/ebp
 1105     5d/pop-to-ebp
 1106     c3/return
 1107 
 1108 test-convert-function-with-arg-and-body:
 1109     # . prologue
 1110     55/push-ebp
 1111     89/<- %ebp 4/r32/esp
 1112     # setup
 1113     (clear-stream _test-input-stream)
 1114     (clear-stream $_test-input-buffered-file->buffer)
 1115     (clear-stream _test-output-stream)
 1116     (clear-stream $_test-output-buffered-file->buffer)
 1117     #
 1118     (write _test-input-stream "fn foo n: int {\n")
 1119     (write _test-input-stream "  increment n\n")
 1120     (write _test-input-stream "}\n")
 1121     # convert
 1122     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1123     (flush _test-output-buffered-file)
 1124 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 1130     # check output
 1131     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-arg-and-body/0")
 1132     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-arg-and-body/1")
 1133     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-arg-and-body/2")
 1134     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-arg-and-body/3")
 1135     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-arg-and-body/4")
 1136     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-arg-and-body/5")
 1137     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *(ebp+0x00000008)"  "F - test-convert-function-with-arg-and-body/6")
 1138     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-arg-and-body/7")
 1139     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-arg-and-body/8")
 1140     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-arg-and-body/9")
 1141     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-arg-and-body/10")
 1142     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-arg-and-body/11")
 1143     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-arg-and-body/12")
 1144     # . epilogue
 1145     89/<- %esp 5/r32/ebp
 1146     5d/pop-to-ebp
 1147     c3/return
 1148 
 1149 test-convert-function-distinguishes-args:
 1150     # . prologue
 1151     55/push-ebp
 1152     89/<- %ebp 4/r32/esp
 1153     # setup
 1154     (clear-stream _test-input-stream)
 1155     (clear-stream $_test-input-buffered-file->buffer)
 1156     (clear-stream _test-output-stream)
 1157     (clear-stream $_test-output-buffered-file->buffer)
 1158     #
 1159     (write _test-input-stream "fn foo a: int, b: int {\n")
 1160     (write _test-input-stream "  increment b\n")
 1161     (write _test-input-stream "}\n")
 1162     # convert
 1163     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1164     (flush _test-output-buffered-file)
 1165 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 1171     # check output
 1172     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-distinguishes-args/0")
 1173     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-distinguishes-args/1")
 1174     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-distinguishes-args/2")
 1175     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-distinguishes-args/3")
 1176     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-distinguishes-args/4")
 1177     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-distinguishes-args/5")
 1178     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *(ebp+0x0000000c)"  "F - test-convert-function-distinguishes-args/6")
 1179     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-distinguishes-args/7")
 1180     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-distinguishes-args/8")
 1181     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-distinguishes-args/9")
 1182     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-distinguishes-args/10")
 1183     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-distinguishes-args/11")
 1184     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-distinguishes-args/12")
 1185     # . epilogue
 1186     89/<- %esp 5/r32/ebp
 1187     5d/pop-to-ebp
 1188     c3/return
 1189 
 1190 test-convert-function-with-return-literal:
 1191     # . prologue
 1192     55/push-ebp
 1193     89/<- %ebp 4/r32/esp
 1194     # setup
 1195     (clear-stream _test-input-stream)
 1196     (clear-stream $_test-input-buffered-file->buffer)
 1197     (clear-stream _test-output-stream)
 1198     (clear-stream $_test-output-buffered-file->buffer)
 1199     #
 1200     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1201     (write _test-input-stream "  return 0\n")
 1202     (write _test-input-stream "}\n")
 1203     # convert
 1204     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1205     (flush _test-output-buffered-file)
 1206 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 1212     # check output
 1213     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-literal/0")
 1214     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-literal/1")
 1215     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-literal/2")
 1216     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-literal/3")
 1217     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-literal/4")
 1218     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-literal/5")
 1219     (check-next-stream-line-equal _test-output-stream "    c7 0/subop/copy %eax 0/imm32"  "F - test-convert-function-with-return-literal/6")
 1220     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-literal/7")
 1221     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-literal/8")
 1222     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-literal/9")
 1223     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-literal/10")
 1224     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-literal/11")
 1225     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-literal/12")
 1226     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-literal/13")
 1227     # . epilogue
 1228     89/<- %esp 5/r32/ebp
 1229     5d/pop-to-ebp
 1230     c3/return
 1231 
 1232 test-convert-function-with-return:
 1233     # . prologue
 1234     55/push-ebp
 1235     89/<- %ebp 4/r32/esp
 1236     # setup
 1237     (clear-stream _test-input-stream)
 1238     (clear-stream $_test-input-buffered-file->buffer)
 1239     (clear-stream _test-output-stream)
 1240     (clear-stream $_test-output-buffered-file->buffer)
 1241     #
 1242     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1243     (write _test-input-stream "  var y: int\n")
 1244     (write _test-input-stream "  return y\n")
 1245     (write _test-input-stream "}\n")
 1246     # convert
 1247     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1248     (flush _test-output-buffered-file)
 1249 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 1255     # check output
 1256     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return/0")
 1257     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return/1")
 1258     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return/2")
 1259     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return/3")
 1260     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return/4")
 1261     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return/5")
 1262     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-return/6")  # y
 1263     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0xfffffffc) 0x00000000/r32" "F - test-convert-function-with-return/7")
 1264     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-return/8")
 1265     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return/9")
 1266     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return/10")
 1267     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return/11")
 1268     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return/12")
 1269     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return/13")
 1270     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return/14")
 1271     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return/15")
 1272     # . epilogue
 1273     89/<- %esp 5/r32/ebp
 1274     5d/pop-to-ebp
 1275     c3/return
 1276 
 1277 test-convert-function-with-return-float:
 1278     # . prologue
 1279     55/push-ebp
 1280     89/<- %ebp 4/r32/esp
 1281     # setup
 1282     (clear-stream _test-input-stream)
 1283     (clear-stream $_test-input-buffered-file->buffer)
 1284     (clear-stream _test-output-stream)
 1285     (clear-stream $_test-output-buffered-file->buffer)
 1286     #
 1287     (write _test-input-stream "fn foo -> _/xmm0: float {\n")
 1288     (write _test-input-stream "  var y: float\n")
 1289     (write _test-input-stream "  return y\n")
 1290     (write _test-input-stream "}\n")
 1291     # convert
 1292     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1293     (flush _test-output-buffered-file)
 1294 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 1300     # check output
 1301     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return/0")
 1302     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return/1")
 1303     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return/2")
 1304     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return/3")
 1305     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return/4")
 1306     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return/5")
 1307     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-return/6")  # y
 1308     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *(ebp+0xfffffffc) 0x00000000/x32" "F - test-convert-function-with-return/7")
 1309     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-return/8")
 1310     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return/9")
 1311     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return/10")
 1312     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return/11")
 1313     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return/12")
 1314     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return/13")
 1315     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return/14")
 1316     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return/15")
 1317     # . epilogue
 1318     89/<- %esp 5/r32/ebp
 1319     5d/pop-to-ebp
 1320     c3/return
 1321 
 1322 test-convert-function-with-return-register:
 1323     # . prologue
 1324     55/push-ebp
 1325     89/<- %ebp 4/r32/esp
 1326     # setup
 1327     (clear-stream _test-input-stream)
 1328     (clear-stream $_test-input-buffered-file->buffer)
 1329     (clear-stream _test-output-stream)
 1330     (clear-stream $_test-output-buffered-file->buffer)
 1331     #
 1332     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1333     (write _test-input-stream "  var y/eax: int <- copy 3\n")
 1334     (write _test-input-stream "  return y\n")
 1335     (write _test-input-stream "}\n")
 1336     # convert
 1337     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1338     (flush _test-output-buffered-file)
 1339 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 1345     # check output
 1346     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-register/0")
 1347     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-register/1")
 1348     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-register/2")
 1349     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-register/3")
 1350     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-register/4")
 1351     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-register/5")
 1352     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-with-return-register/6")
 1353     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 3/imm32"  "F - test-convert-function-with-return-register/7")
 1354     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32" "F - test-convert-function-with-return-register/8")
 1355     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-with-return-register/9")
 1356     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-register/10")
 1357     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-register/11")
 1358     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-register/12")
 1359     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-register/13")
 1360     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-register/14")
 1361     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-register/15")
 1362     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-register/16")
 1363     # . epilogue
 1364     89/<- %esp 5/r32/ebp
 1365     5d/pop-to-ebp
 1366     c3/return
 1367 
 1368 test-function-with-output-without-register:
 1369     # . prologue
 1370     55/push-ebp
 1371     89/<- %ebp 4/r32/esp
 1372     # setup
 1373     (clear-stream _test-input-stream)
 1374     (clear-stream $_test-input-buffered-file->buffer)
 1375     (clear-stream _test-output-stream)
 1376     (clear-stream $_test-output-buffered-file->buffer)
 1377     (clear-stream _test-error-stream)
 1378     (clear-stream $_test-error-buffered-file->buffer)
 1379     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1380     68/push 0/imm32
 1381     68/push 0/imm32
 1382     89/<- %edx 4/r32/esp
 1383     (tailor-exit-descriptor %edx 0x10)
 1384     #
 1385     (write _test-input-stream "fn foo -> _: int {\n")
 1386     (write _test-input-stream "}\n")
 1387     # convert
 1388     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1389     # registers except esp clobbered at this point
 1390     # restore ed
 1391     89/<- %edx 4/r32/esp
 1392     (flush _test-output-buffered-file)
 1393     (flush _test-error-buffered-file)
 1394 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1400     # check output
 1401     (check-stream-equal _test-output-stream  ""  "F - test-function-with-output-without-register: output should be empty")
 1402     (check-next-stream-line-equal _test-error-stream  "fn foo: function output '_' must be in a register, in instruction 'fn foo -> _: int {"  "F - test-function-with-output-without-register: error message")
 1403     # check that stop(1) was called
 1404     (check-ints-equal *(edx+4) 2 "F - test-function-with-output-without-register: exit status")
 1405     # don't restore from ebp
 1406     81 0/subop/add %esp 8/imm32
 1407     # . epilogue
 1408     5d/pop-to-ebp
 1409     c3/return
 1410 
 1411 test-function-with-outputs-in-conflicting-registers:
 1412     # . prologue
 1413     55/push-ebp
 1414     89/<- %ebp 4/r32/esp
 1415     # setup
 1416     (clear-stream _test-input-stream)
 1417     (clear-stream $_test-input-buffered-file->buffer)
 1418     (clear-stream _test-output-stream)
 1419     (clear-stream $_test-output-buffered-file->buffer)
 1420     (clear-stream _test-error-stream)
 1421     (clear-stream $_test-error-buffered-file->buffer)
 1422     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1423     68/push 0/imm32
 1424     68/push 0/imm32
 1425     89/<- %edx 4/r32/esp
 1426     (tailor-exit-descriptor %edx 0x10)
 1427     #
 1428     (write _test-input-stream "fn foo -> _/eax: int, _/eax: int {\n")
 1429     (write _test-input-stream "}\n")
 1430     # convert
 1431     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1432     # registers except esp clobbered at this point
 1433     # restore ed
 1434     89/<- %edx 4/r32/esp
 1435     (flush _test-output-buffered-file)
 1436     (flush _test-error-buffered-file)
 1437 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1443     # check output
 1444     (check-stream-equal _test-output-stream  ""  "F - test-function-with-outputs-in-conflicting-registers: output should be empty")
 1445     (check-next-stream-line-equal _test-error-stream  "fn foo: outputs must be in unique registers"  "F - test-function-with-outputs-in-conflicting-registers: error message")
 1446     # check that stop(1) was called
 1447     (check-ints-equal *(edx+4) 2 "F - test-function-with-outputs-in-conflicting-registers: exit status")
 1448     # don't restore from ebp
 1449     81 0/subop/add %esp 8/imm32
 1450     # . epilogue
 1451     5d/pop-to-ebp
 1452     c3/return
 1453 
 1454 test-function-with-named-output:
 1455     # . prologue
 1456     55/push-ebp
 1457     89/<- %ebp 4/r32/esp
 1458     # setup
 1459     (clear-stream _test-input-stream)
 1460     (clear-stream $_test-input-buffered-file->buffer)
 1461     (clear-stream _test-output-stream)
 1462     (clear-stream $_test-output-buffered-file->buffer)
 1463     (clear-stream _test-error-stream)
 1464     (clear-stream $_test-error-buffered-file->buffer)
 1465     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1466     68/push 0/imm32
 1467     68/push 0/imm32
 1468     89/<- %edx 4/r32/esp
 1469     (tailor-exit-descriptor %edx 0x10)
 1470     #
 1471     (write _test-input-stream "fn foo -> x/eax: int {\n")
 1472     (write _test-input-stream "  return 0\n")
 1473     (write _test-input-stream "}\n")
 1474     # convert
 1475     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1476     # registers except esp clobbered at this point
 1477     # restore ed
 1478     89/<- %edx 4/r32/esp
 1479     (flush _test-output-buffered-file)
 1480     (flush _test-error-buffered-file)
 1481 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1487     # check output
 1488     (check-stream-equal _test-output-stream  ""  "F - test-function-with-named-output: output should be empty")
 1489     (check-next-stream-line-equal _test-error-stream  "fn foo: function outputs cannot be named; rename 'x' in the header to '_'"  "F - test-function-with-named-output: error message")
 1490     # check that stop(1) was called
 1491     (check-ints-equal *(edx+4) 2 "F - test-function-with-named-output: exit status")
 1492     # don't restore from ebp
 1493     81 0/subop/add %esp 8/imm32
 1494     # . epilogue
 1495     5d/pop-to-ebp
 1496     c3/return
 1497 
 1498 test-return-with-wrong-type:
 1499     # . prologue
 1500     55/push-ebp
 1501     89/<- %ebp 4/r32/esp
 1502     # setup
 1503     (clear-stream _test-input-stream)
 1504     (clear-stream $_test-input-buffered-file->buffer)
 1505     (clear-stream _test-output-stream)
 1506     (clear-stream $_test-output-buffered-file->buffer)
 1507     (clear-stream _test-error-stream)
 1508     (clear-stream $_test-error-buffered-file->buffer)
 1509     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1510     68/push 0/imm32
 1511     68/push 0/imm32
 1512     89/<- %edx 4/r32/esp
 1513     (tailor-exit-descriptor %edx 0x10)
 1514     #
 1515     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1516     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
 1517     (write _test-input-stream "  return x\n")
 1518     (write _test-input-stream "}\n")
 1519     # convert
 1520     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1521     # registers except esp clobbered at this point
 1522     # restore ed
 1523     89/<- %edx 4/r32/esp
 1524     (flush _test-output-buffered-file)
 1525     (flush _test-error-buffered-file)
 1526 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1532     # check output
 1533     (check-stream-equal _test-output-stream  ""  "F - test-return-with-wrong-type: output should be empty")
 1534     (check-next-stream-line-equal _test-error-stream  "fn foo: return: 'x' has the wrong type"  "F - test-return-with-wrong-type: error message")
 1535     # check that stop(1) was called
 1536     (check-ints-equal *(edx+4) 2 "F - test-return-with-wrong-type: exit status")
 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-missing-return:
 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     (clear-stream _test-error-stream)
 1553     (clear-stream $_test-error-buffered-file->buffer)
 1554     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1555     68/push 0/imm32
 1556     68/push 0/imm32
 1557     89/<- %edx 4/r32/esp
 1558     (tailor-exit-descriptor %edx 0x10)
 1559     #
 1560     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1561     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
 1562     (write _test-input-stream "}\n")
 1563     # convert
 1564     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1565     # registers except esp clobbered at this point
 1566     # restore ed
 1567     89/<- %edx 4/r32/esp
 1568     (flush _test-output-buffered-file)
 1569     (flush _test-error-buffered-file)
 1570 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1576     # check output
 1577     (check-stream-equal _test-output-stream  ""  "F - test-missing-return: output should be empty")
 1578     (check-next-stream-line-equal _test-error-stream  "fn foo: final statement should be a 'return'"  "F - test-missing-return: error message")
 1579     # check that stop(1) was called
 1580     (check-ints-equal *(edx+4) 2 "F - test-missing-return: exit status")
 1581     # don't restore from ebp
 1582     81 0/subop/add %esp 8/imm32
 1583     # . epilogue
 1584     5d/pop-to-ebp
 1585     c3/return
 1586 
 1587 test-missing-return-2:
 1588     # . prologue
 1589     55/push-ebp
 1590     89/<- %ebp 4/r32/esp
 1591     # setup
 1592     (clear-stream _test-input-stream)
 1593     (clear-stream $_test-input-buffered-file->buffer)
 1594     (clear-stream _test-output-stream)
 1595     (clear-stream $_test-output-buffered-file->buffer)
 1596     (clear-stream _test-error-stream)
 1597     (clear-stream $_test-error-buffered-file->buffer)
 1598     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1599     68/push 0/imm32
 1600     68/push 0/imm32
 1601     89/<- %edx 4/r32/esp
 1602     (tailor-exit-descriptor %edx 0x10)
 1603     #
 1604     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1605     (write _test-input-stream "}\n")
 1606     # convert
 1607     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1608     # registers except esp clobbered at this point
 1609     # restore ed
 1610     89/<- %edx 4/r32/esp
 1611     (flush _test-output-buffered-file)
 1612     (flush _test-error-buffered-file)
 1613 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1619     # check output
 1620     (check-stream-equal _test-output-stream  ""  "F - test-missing-return-2: output should be empty")
 1621     (check-next-stream-line-equal _test-error-stream  "fn foo: final statement should be a 'return'"  "F - test-missing-return-2: error message")
 1622     # check that stop(1) was called
 1623     (check-ints-equal *(edx+4) 2 "F - test-missing-return-2: exit status")
 1624     # don't restore from ebp
 1625     81 0/subop/add %esp 8/imm32
 1626     # . epilogue
 1627     5d/pop-to-ebp
 1628     c3/return
 1629 
 1630 test-early-exit-without-return:
 1631     # . prologue
 1632     55/push-ebp
 1633     89/<- %ebp 4/r32/esp
 1634     # setup
 1635     (clear-stream _test-input-stream)
 1636     (clear-stream $_test-input-buffered-file->buffer)
 1637     (clear-stream _test-output-stream)
 1638     (clear-stream $_test-output-buffered-file->buffer)
 1639     (clear-stream _test-error-stream)
 1640     (clear-stream $_test-error-buffered-file->buffer)
 1641     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1642     68/push 0/imm32
 1643     68/push 0/imm32
 1644     89/<- %edx 4/r32/esp
 1645     (tailor-exit-descriptor %edx 0x10)
 1646     #
 1647     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1648     (write _test-input-stream "  break\n")
 1649     (write _test-input-stream "  return 0\n")
 1650     (write _test-input-stream "}\n")
 1651     # convert
 1652     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1653     # registers except esp clobbered at this point
 1654     # restore ed
 1655     89/<- %edx 4/r32/esp
 1656     (flush _test-output-buffered-file)
 1657     (flush _test-error-buffered-file)
 1658 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1664     # check output
 1665     (check-stream-equal _test-output-stream  ""  "F - test-early-exit-without-return: output should be empty")
 1666     (check-next-stream-line-equal _test-error-stream  "fn foo has outputs, so you cannot 'break' out of the outermost block. Use 'return'."  "F - test-early-exit-without-return: error message")
 1667     # check that stop(1) was called
 1668     (check-ints-equal *(edx+4) 2 "F - test-early-exit-without-return: exit status")
 1669     # don't restore from ebp
 1670     81 0/subop/add %esp 8/imm32
 1671     # . epilogue
 1672     5d/pop-to-ebp
 1673     c3/return
 1674 
 1675 test-return-with-too-few-inouts:
 1676     # . prologue
 1677     55/push-ebp
 1678     89/<- %ebp 4/r32/esp
 1679     # setup
 1680     (clear-stream _test-input-stream)
 1681     (clear-stream $_test-input-buffered-file->buffer)
 1682     (clear-stream _test-output-stream)
 1683     (clear-stream $_test-output-buffered-file->buffer)
 1684     (clear-stream _test-error-stream)
 1685     (clear-stream $_test-error-buffered-file->buffer)
 1686     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1687     68/push 0/imm32
 1688     68/push 0/imm32
 1689     89/<- %edx 4/r32/esp
 1690     (tailor-exit-descriptor %edx 0x10)
 1691     #
 1692     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1693     (write _test-input-stream "  return\n")
 1694     (write _test-input-stream "}\n")
 1695     # convert
 1696     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1697     # registers except esp clobbered at this point
 1698     # restore ed
 1699     89/<- %edx 4/r32/esp
 1700     (flush _test-output-buffered-file)
 1701     (flush _test-error-buffered-file)
 1702 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1708     # check output
 1709     (check-stream-equal _test-output-stream  ""  "F - test-return-with-too-few-inouts: output should be empty")
 1710     (check-next-stream-line-equal _test-error-stream  "fn foo: return: too few inouts"  "F - test-return-with-too-few-inouts: error message")
 1711     # check that stop(1) was called
 1712     (check-ints-equal *(edx+4) 2 "F - test-return-with-too-few-inouts: exit status")
 1713     # don't restore from ebp
 1714     81 0/subop/add %esp 8/imm32
 1715     # . epilogue
 1716     5d/pop-to-ebp
 1717     c3/return
 1718 
 1719 test-return-with-too-many-inouts:
 1720     # . prologue
 1721     55/push-ebp
 1722     89/<- %ebp 4/r32/esp
 1723     # setup
 1724     (clear-stream _test-input-stream)
 1725     (clear-stream $_test-input-buffered-file->buffer)
 1726     (clear-stream _test-output-stream)
 1727     (clear-stream $_test-output-buffered-file->buffer)
 1728     (clear-stream _test-error-stream)
 1729     (clear-stream $_test-error-buffered-file->buffer)
 1730     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1731     68/push 0/imm32
 1732     68/push 0/imm32
 1733     89/<- %edx 4/r32/esp
 1734     (tailor-exit-descriptor %edx 0x10)
 1735     #
 1736     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1737     (write _test-input-stream "  return 0, 0\n")
 1738     (write _test-input-stream "}\n")
 1739     # convert
 1740     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1741     # registers except esp clobbered at this point
 1742     # restore ed
 1743     89/<- %edx 4/r32/esp
 1744     (flush _test-output-buffered-file)
 1745     (flush _test-error-buffered-file)
 1746 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1752     # check output
 1753     (check-stream-equal _test-output-stream  ""  "F - test-return-with-too-many-inouts: output should be empty")
 1754     (check-next-stream-line-equal _test-error-stream  "fn foo: return: too many inouts"  "F - test-return-with-too-many-inouts: error message")
 1755     # check that stop(1) was called
 1756     (check-ints-equal *(edx+4) 2 "F - test-return-with-too-many-inouts: exit status")
 1757     # don't restore from ebp
 1758     81 0/subop/add %esp 8/imm32
 1759     # . epilogue
 1760     5d/pop-to-ebp
 1761     c3/return
 1762 
 1763 test-return-unavailable-value:
 1764     # . prologue
 1765     55/push-ebp
 1766     89/<- %ebp 4/r32/esp
 1767     # setup
 1768     (clear-stream _test-input-stream)
 1769     (clear-stream $_test-input-buffered-file->buffer)
 1770     (clear-stream _test-output-stream)
 1771     (clear-stream $_test-output-buffered-file->buffer)
 1772     (clear-stream _test-error-stream)
 1773     (clear-stream $_test-error-buffered-file->buffer)
 1774     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1775     68/push 0/imm32
 1776     68/push 0/imm32
 1777     89/<- %edx 4/r32/esp
 1778     (tailor-exit-descriptor %edx 0x10)
 1779     #
 1780     (write _test-input-stream "fn foo -> _/eax: int, _/ecx: int {\n")
 1781     (write _test-input-stream "  var x/eax: int <- copy 0\n")
 1782     (write _test-input-stream "  var y/ecx: int <- copy 0\n")
 1783     (write _test-input-stream "  return y, x\n")
 1784     (write _test-input-stream "}\n")
 1785     # convert
 1786     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1787     # registers except esp clobbered at this point
 1788     # restore ed
 1789     89/<- %edx 4/r32/esp
 1790     (flush _test-output-buffered-file)
 1791     (flush _test-error-buffered-file)
 1792 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1798     # check output
 1799     (check-stream-equal _test-output-stream  ""  "F - test-return-unavailable-value: output should be empty")
 1800     (check-next-stream-line-equal _test-error-stream  "fn foo: return: 'x' is no longer available"  "F - test-return-unavailable-value: error message")
 1801     # check that stop(1) was called
 1802     (check-ints-equal *(edx+4) 2 "F - test-return-unavailable-value: exit status")
 1803     # don't restore from ebp
 1804     81 0/subop/add %esp 8/imm32
 1805     # . epilogue
 1806     5d/pop-to-ebp
 1807     c3/return
 1808 
 1809 test-return-literal-to-float:
 1810     # . prologue
 1811     55/push-ebp
 1812     89/<- %ebp 4/r32/esp
 1813     # setup
 1814     (clear-stream _test-input-stream)
 1815     (clear-stream $_test-input-buffered-file->buffer)
 1816     (clear-stream _test-output-stream)
 1817     (clear-stream $_test-output-buffered-file->buffer)
 1818     (clear-stream _test-error-stream)
 1819     (clear-stream $_test-error-buffered-file->buffer)
 1820     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1821     68/push 0/imm32
 1822     68/push 0/imm32
 1823     89/<- %edx 4/r32/esp
 1824     (tailor-exit-descriptor %edx 0x10)
 1825     #
 1826     (write _test-input-stream "fn foo -> _/xmm0: float {\n")
 1827     (write _test-input-stream "  return 0\n")
 1828     (write _test-input-stream "}\n")
 1829     # convert
 1830     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1831     # registers except esp clobbered at this point
 1832     # restore ed
 1833     89/<- %edx 4/r32/esp
 1834     (flush _test-output-buffered-file)
 1835     (flush _test-error-buffered-file)
 1836 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1842     # check output
 1843     (check-stream-equal _test-output-stream  ""  "F - test-return-literal-to-float: output should be empty")
 1844     (check-next-stream-line-equal _test-error-stream  "fn foo: return: cannot copy literal '0' to float"  "F - test-return-literal-to-float: error message")
 1845     # check that stop(1) was called
 1846     (check-ints-equal *(edx+4) 2 "F - test-return-literal-to-float: exit status")
 1847     # don't restore from ebp
 1848     81 0/subop/add %esp 8/imm32
 1849     # . epilogue
 1850     5d/pop-to-ebp
 1851     c3/return
 1852 
 1853 test-convert-return-with-duplicate-values:
 1854     # . prologue
 1855     55/push-ebp
 1856     89/<- %ebp 4/r32/esp
 1857     # setup
 1858     (clear-stream _test-input-stream)
 1859     (clear-stream $_test-input-buffered-file->buffer)
 1860     (clear-stream _test-output-stream)
 1861     (clear-stream $_test-output-buffered-file->buffer)
 1862     #
 1863     (write _test-input-stream "fn foo -> _/eax: int, _/ecx: int {\n")
 1864     (write _test-input-stream "  var x/eax: int <- copy 0x34\n")
 1865     (write _test-input-stream "  return x, x\n")
 1866     (write _test-input-stream "}\n")
 1867     # convert
 1868     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1869     (flush _test-output-buffered-file)
 1870 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 1876     # check output
 1877     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-return-with-duplicate-values/0")
 1878     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-return-with-duplicate-values/1")
 1879     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-return-with-duplicate-values/2")
 1880     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-return-with-duplicate-values/3")
 1881     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-return-with-duplicate-values/4")
 1882     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-return-with-duplicate-values/5")
 1883     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-return-with-duplicate-values/6")
 1884     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0x34/imm32"  "F - test-convert-return-with-duplicate-values/7")
 1885     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32"  "F - test-convert-return-with-duplicate-values/8")
 1886     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000001/r32"  "F - test-convert-return-with-duplicate-values/9")
 1887     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-return-with-duplicate-values/10")
 1888     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-return-with-duplicate-values/11")
 1889     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-return-with-duplicate-values/12")
 1890     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-return-with-duplicate-values/13")
 1891     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-return-with-duplicate-values/14")
 1892     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-return-with-duplicate-values/15")
 1893     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-return-with-duplicate-values/16")
 1894     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-return-with-duplicate-values/17")
 1895     # . epilogue
 1896     89/<- %esp 5/r32/ebp
 1897     5d/pop-to-ebp
 1898     c3/return
 1899 
 1900 test-convert-return-with-duplicate-values-2:
 1901     # . prologue
 1902     55/push-ebp
 1903     89/<- %ebp 4/r32/esp
 1904     # setup
 1905     (clear-stream _test-input-stream)
 1906     (clear-stream $_test-input-buffered-file->buffer)
 1907     (clear-stream _test-output-stream)
 1908     (clear-stream $_test-output-buffered-file->buffer)
 1909     #
 1910     (write _test-input-stream "fn foo -> _/eax: int, _/ecx: int {\n")
 1911     (write _test-input-stream "  var x/ecx: int <- copy 0x34\n")
 1912     (write _test-input-stream "  return x, x\n")
 1913     (write _test-input-stream "}\n")
 1914     # convert
 1915     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1916     (flush _test-output-buffered-file)
 1917 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 1923     # check output
 1924     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-return-with-duplicate-values-2/0")
 1925     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-return-with-duplicate-values-2/1")
 1926     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-return-with-duplicate-values-2/2")
 1927     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-return-with-duplicate-values-2/3")
 1928     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-return-with-duplicate-values-2/4")
 1929     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-return-with-duplicate-values-2/5")
 1930     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-return-with-duplicate-values-2/6")
 1931     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0x34/imm32"  "F - test-convert-return-with-duplicate-values-2/7")
 1932     (check-next-stream-line-equal _test-output-stream "    8b/-> %ecx 0x00000000/r32"  "F - test-convert-return-with-duplicate-values-2/8")
 1933     (check-next-stream-line-equal _test-output-stream "    8b/-> %ecx 0x00000001/r32"  "F - test-convert-return-with-duplicate-values-2/9")
 1934     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-return-with-duplicate-values-2/10")
 1935     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-return-with-duplicate-values-2/11")
 1936     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-return-with-duplicate-values-2/12")
 1937     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-return-with-duplicate-values-2/13")
 1938     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-return-with-duplicate-values-2/14")
 1939     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-return-with-duplicate-values-2/15")
 1940     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-return-with-duplicate-values-2/16")
 1941     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-return-with-duplicate-values-2/17")
 1942     # . epilogue
 1943     89/<- %esp 5/r32/ebp
 1944     5d/pop-to-ebp
 1945     c3/return
 1946 
 1947 test-stmt-with-unknown-var:
 1948     # . prologue
 1949     55/push-ebp
 1950     89/<- %ebp 4/r32/esp
 1951     # setup
 1952     (clear-stream _test-input-stream)
 1953     (clear-stream $_test-input-buffered-file->buffer)
 1954     (clear-stream _test-output-stream)
 1955     (clear-stream $_test-output-buffered-file->buffer)
 1956     (clear-stream _test-error-stream)
 1957     (clear-stream $_test-error-buffered-file->buffer)
 1958     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1959     68/push 0/imm32
 1960     68/push 0/imm32
 1961     89/<- %edx 4/r32/esp
 1962     (tailor-exit-descriptor %edx 0x10)
 1963     #
 1964     (write _test-input-stream "fn foo {\n")
 1965     (write _test-input-stream "  x <- copy 0x34\n")
 1966     (write _test-input-stream "}\n")
 1967     # convert
 1968     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1969     # registers except esp clobbered at this point
 1970     # restore ed
 1971     89/<- %edx 4/r32/esp
 1972     (flush _test-output-buffered-file)
 1973     (flush _test-error-buffered-file)
 1974 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1980     # check output
 1981     (check-stream-equal _test-output-stream  ""  "F - test-stmt-with-unknown-var: output should be empty")
 1982     (check-next-stream-line-equal _test-error-stream  "fn foo: unknown variable 'x'"  "F - test-stmt-with-unknown-var: error message")
 1983     # check that stop(1) was called
 1984     (check-ints-equal *(edx+4) 2 "F - test-stmt-with-unknown-var: exit status")
 1985     # don't restore from ebp
 1986     81 0/subop/add %esp 8/imm32
 1987     # . epilogue
 1988     5d/pop-to-ebp
 1989     c3/return
 1990 
 1991 test-stmt-with-invalid-identifier:
 1992     # . prologue
 1993     55/push-ebp
 1994     89/<- %ebp 4/r32/esp
 1995     # setup
 1996     (clear-stream _test-input-stream)
 1997     (clear-stream $_test-input-buffered-file->buffer)
 1998     (clear-stream _test-output-stream)
 1999     (clear-stream $_test-output-buffered-file->buffer)
 2000     (clear-stream _test-error-stream)
 2001     (clear-stream $_test-error-buffered-file->buffer)
 2002     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2003     68/push 0/imm32
 2004     68/push 0/imm32
 2005     89/<- %edx 4/r32/esp
 2006     (tailor-exit-descriptor %edx 0x10)
 2007     #
 2008     (write _test-input-stream "fn foo {\n")
 2009     (write _test-input-stream "  1 <- copy 0x34\n")
 2010     (write _test-input-stream "}\n")
 2011     # convert
 2012     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2013     # registers except esp clobbered at this point
 2014     # restore ed
 2015     89/<- %edx 4/r32/esp
 2016     (flush _test-output-buffered-file)
 2017     (flush _test-error-buffered-file)
 2018 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2024     # check output
 2025     (check-stream-equal _test-output-stream  ""  "F - test-stmt-with-invalid-identifier: output should be empty")
 2026     (check-next-stream-line-equal _test-error-stream  "fn foo: invalid identifier '1'"  "F - test-stmt-with-invalid-identifier: error message")
 2027     # check that stop(1) was called
 2028     (check-ints-equal *(edx+4) 2 "F - test-stmt-with-invalid-identifier: exit status")
 2029     # don't restore from ebp
 2030     81 0/subop/add %esp 8/imm32
 2031     # . epilogue
 2032     5d/pop-to-ebp
 2033     c3/return
 2034 
 2035 test-stmt-with-deref-var:
 2036     # . prologue
 2037     55/push-ebp
 2038     89/<- %ebp 4/r32/esp
 2039     # setup
 2040     (clear-stream _test-input-stream)
 2041     (clear-stream $_test-input-buffered-file->buffer)
 2042     (clear-stream _test-output-stream)
 2043     (clear-stream $_test-output-buffered-file->buffer)
 2044     (clear-stream _test-error-stream)
 2045     (clear-stream $_test-error-buffered-file->buffer)
 2046     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2047     68/push 0/imm32
 2048     68/push 0/imm32
 2049     89/<- %edx 4/r32/esp
 2050     (tailor-exit-descriptor %edx 0x10)
 2051     #
 2052     (write _test-input-stream "fn foo {\n")
 2053     (write _test-input-stream "  *x <- copy 0x34\n")
 2054     (write _test-input-stream "}\n")
 2055     # convert
 2056     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2057     # registers except esp clobbered at this point
 2058     # restore ed
 2059     89/<- %edx 4/r32/esp
 2060     (flush _test-output-buffered-file)
 2061     (flush _test-error-buffered-file)
 2062 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2068     # check output
 2069     (check-stream-equal _test-output-stream  ""  "F - test-stmt-with-deref-var: output should be empty")
 2070     (check-next-stream-line-equal _test-error-stream  "fn foo: output '*x' should write to a register, and therefore cannot be dereferenced"  "F - test-stmt-with-deref-var: error message")
 2071     # check that stop(1) was called
 2072     (check-ints-equal *(edx+4) 2 "F - test-stmt-with-deref-var: exit status")
 2073     # don't restore from ebp
 2074     81 0/subop/add %esp 8/imm32
 2075     # . epilogue
 2076     5d/pop-to-ebp
 2077     c3/return
 2078 
 2079 test-convert-function-with-literal-arg:
 2080     # . prologue
 2081     55/push-ebp
 2082     89/<- %ebp 4/r32/esp
 2083     # setup
 2084     (clear-stream _test-input-stream)
 2085     (clear-stream $_test-input-buffered-file->buffer)
 2086     (clear-stream _test-output-stream)
 2087     (clear-stream $_test-output-buffered-file->buffer)
 2088     #
 2089     (write _test-input-stream "fn foo a: int, b: int -> _/eax: int {\n")
 2090     (write _test-input-stream "  var result/eax: int <- copy a\n")
 2091     (write _test-input-stream "  result <- add 1\n")
 2092     (write _test-input-stream "  return result\n")
 2093     (write _test-input-stream "}\n")
 2094     # convert
 2095     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2096     (flush _test-output-buffered-file)
 2097 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2103     # check output
 2104     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-literal-arg/0")
 2105     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-literal-arg/1")
 2106     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-literal-arg/2")
 2107     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-literal-arg/3")
 2108     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-literal-arg/4")
 2109     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-literal-arg/5")
 2110     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-with-literal-arg/6")
 2111     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-function-with-literal-arg/7")
 2112     (check-next-stream-line-equal _test-output-stream "    05/add-to-eax 1/imm32"  "F - test-convert-function-with-literal-arg/8")
 2113     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32" "F - test-convert-function-with-literal-arg/9")
 2114     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-with-literal-arg/10")
 2115     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-literal-arg/11")
 2116     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-literal-arg/12")
 2117     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-literal-arg/13")
 2118     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-literal-arg/14")
 2119     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-literal-arg/15")
 2120     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-literal-arg/16")
 2121     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-literal-arg/17")
 2122     # . epilogue
 2123     89/<- %esp 5/r32/ebp
 2124     5d/pop-to-ebp
 2125     c3/return
 2126 
 2127 test-convert-function-with-literal-arg-2:
 2128     # . prologue
 2129     55/push-ebp
 2130     89/<- %ebp 4/r32/esp
 2131     # setup
 2132     (clear-stream _test-input-stream)
 2133     (clear-stream $_test-input-buffered-file->buffer)
 2134     (clear-stream _test-output-stream)
 2135     (clear-stream $_test-output-buffered-file->buffer)
 2136     #
 2137     (write _test-input-stream "fn foo a: int, b: int -> _/ebx: int {\n")
 2138     (write _test-input-stream "  var result/ebx: int <- copy a\n")
 2139     (write _test-input-stream "  result <- add 1\n")
 2140     (write _test-input-stream "  return result\n")
 2141     (write _test-input-stream "}\n")
 2142     # convert
 2143     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2144     (flush _test-output-buffered-file)
 2145 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2151     # check output
 2152     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-literal-arg-2/0")
 2153     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-literal-arg-2/1")
 2154     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-literal-arg-2/2")
 2155     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-literal-arg-2/3")
 2156     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-literal-arg-2/4")
 2157     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-literal-arg-2/5")
 2158     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ebx"  "F - test-convert-function-with-literal-arg-2/6")
 2159     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000003/r32"  "F - test-convert-function-with-literal-arg-2/7")
 2160     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %ebx 1/imm32"  "F - test-convert-function-with-literal-arg-2/8")
 2161     (check-next-stream-line-equal _test-output-stream "    8b/-> %ebx 0x00000003/r32" "F - test-convert-function-with-literal-arg-2/9")
 2162     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-with-literal-arg-2/10")
 2163     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-literal-arg-2/11")
 2164     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-literal-arg-2/12")
 2165     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-literal-arg-2/13")
 2166     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-literal-arg-2/14")
 2167     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-literal-arg-2/15")
 2168     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-literal-arg-2/16")
 2169     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-literal-arg-2/17")
 2170     # . epilogue
 2171     89/<- %esp 5/r32/ebp
 2172     5d/pop-to-ebp
 2173     c3/return
 2174 
 2175 test-convert-function-call-with-literal-arg:
 2176     # . prologue
 2177     55/push-ebp
 2178     89/<- %ebp 4/r32/esp
 2179     # setup
 2180     (clear-stream _test-input-stream)
 2181     (clear-stream $_test-input-buffered-file->buffer)
 2182     (clear-stream _test-output-stream)
 2183     (clear-stream $_test-output-buffered-file->buffer)
 2184     #
 2185     (write _test-input-stream "fn main -> _/ebx: int {\n")
 2186     (write _test-input-stream "  var result/eax: int <- do-add 3 4\n")
 2187     (write _test-input-stream "  return result\n")
 2188     (write _test-input-stream "}\n")
 2189     (write _test-input-stream "fn do-add a: int, b: int -> _/eax: int {\n")
 2190     (write _test-input-stream "  var result/eax: int <- copy a\n")
 2191     (write _test-input-stream "  result <- add b\n")
 2192     (write _test-input-stream "  return result\n")
 2193     (write _test-input-stream "}\n")
 2194     # convert
 2195     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2196     (flush _test-output-buffered-file)
 2197 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2203     # check output
 2204     (check-next-stream-line-equal _test-output-stream "main:"                   "F - test-convert-function-call-with-literal-arg/0")
 2205     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-literal-arg/1")
 2206     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-literal-arg/2")
 2207     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-literal-arg/3")
 2208     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-literal-arg/4")
 2209     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:loop:"  "F - test-convert-function-call-with-literal-arg/5")
 2210     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-call-with-literal-arg/6")
 2211     (check-next-stream-line-equal _test-output-stream "    (do-add 3 4)"        "F - test-convert-function-call-with-literal-arg/7")
 2212     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/8")
 2213     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-function-with-local-var-in-reg/9")
 2214     (check-next-stream-line-equal _test-output-stream "    e9/jump $main:0x00000001:break/disp32"  "F - test-convert-function-call-with-literal-arg/10")
 2215     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-literal-arg/11")
 2216     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:break:" "F - test-convert-function-call-with-literal-arg/12")
 2217     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-literal-arg/13")
 2218     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-literal-arg/14")
 2219     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-literal-arg/15")
 2220     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-literal-arg/16")
 2221     (check-next-stream-line-equal _test-output-stream "do-add:"                 "F - test-convert-function-call-with-literal-arg/17")
 2222     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-literal-arg/18")
 2223     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-literal-arg/19")
 2224     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-literal-arg/20")
 2225     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-literal-arg/21")
 2226     (check-next-stream-line-equal _test-output-stream "$do-add:0x00000002:loop:"  "F - test-convert-function-call-with-literal-arg/22")
 2227     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-call-with-literal-arg/23")
 2228     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-function-call-with-literal-arg/24")
 2229     (check-next-stream-line-equal _test-output-stream "    03/add *(ebp+0x0000000c) 0x00000000/r32"  "F - test-convert-function-call-with-literal-arg/25")
 2230     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32" "F - test-convert-function-call-with-literal-arg/26")
 2231     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-call-with-literal-arg/27")
 2232     (check-next-stream-line-equal _test-output-stream "    e9/jump $do-add:0x00000002:break/disp32"  "F - test-convert-function-call-with-literal-arg/28")
 2233     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-literal-arg/29")
 2234     (check-next-stream-line-equal _test-output-stream "$do-add:0x00000002:break:"  "F - test-convert-function-call-with-literal-arg/30")
 2235     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-literal-arg/31")
 2236     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-literal-arg/32")
 2237     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-literal-arg/33")
 2238     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-literal-arg/34")
 2239     # . epilogue
 2240     89/<- %esp 5/r32/ebp
 2241     5d/pop-to-ebp
 2242     c3/return
 2243 
 2244 test-convert-function-call-with-literal-string-arg:
 2245     # . prologue
 2246     55/push-ebp
 2247     89/<- %ebp 4/r32/esp
 2248     # setup
 2249     (clear-stream _test-input-stream)
 2250     (clear-stream $_test-input-buffered-file->buffer)
 2251     (clear-stream _test-output-stream)
 2252     (clear-stream $_test-output-buffered-file->buffer)
 2253     #
 2254     (write _test-input-stream "fn foo {\n")
 2255     (write _test-input-stream "  string-func \"abc\"\n")
 2256     (write _test-input-stream "}\n")
 2257     (write _test-input-stream "sig string-func in: (addr array byte)\n")
 2258     # convert
 2259     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2260     # no errors
 2261     # not bothering checking output
 2262     # . epilogue
 2263     89/<- %esp 5/r32/ebp
 2264     5d/pop-to-ebp
 2265     c3/return
 2266 
 2267 test-convert-function-call-with-null-addr:
 2268     # . prologue
 2269     55/push-ebp
 2270     89/<- %ebp 4/r32/esp
 2271     # setup
 2272     (clear-stream _test-input-stream)
 2273     (clear-stream $_test-input-buffered-file->buffer)
 2274     (clear-stream _test-output-stream)
 2275     (clear-stream $_test-output-buffered-file->buffer)
 2276     #
 2277     (write _test-input-stream "fn foo {\n")
 2278     (write _test-input-stream "  bar 0\n")
 2279     (write _test-input-stream "}\n")
 2280     (write _test-input-stream "sig bar in: (addr int)\n")
 2281     # convert
 2282     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2283     # no errors
 2284     # not bothering checking output
 2285     # . epilogue
 2286     89/<- %esp 5/r32/ebp
 2287     5d/pop-to-ebp
 2288     c3/return
 2289 
 2290 test-convert-function-call-with-signature:
 2291     # . prologue
 2292     55/push-ebp
 2293     89/<- %ebp 4/r32/esp
 2294     # setup
 2295     (clear-stream _test-input-stream)
 2296     (clear-stream $_test-input-buffered-file->buffer)
 2297     (clear-stream _test-output-stream)
 2298     (clear-stream $_test-output-buffered-file->buffer)
 2299     #
 2300     (write _test-input-stream "fn main -> _/ebx: int {\n")
 2301     (write _test-input-stream "  var result/eax: int <- do-add 3 4\n")
 2302     (write _test-input-stream "  return result\n")
 2303     (write _test-input-stream "}\n")
 2304     (write _test-input-stream "sig do-add a: int, b: int -> _/eax: int\n")
 2305     # convert
 2306     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2307     (flush _test-output-buffered-file)
 2308 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2314     # check output
 2315     (check-next-stream-line-equal _test-output-stream "main:"                   "F - test-convert-function-call-with-signature/0")
 2316     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-signature/1")
 2317     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-signature/2")
 2318     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-signature/3")
 2319     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-signature/4")
 2320     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:loop:"  "F - test-convert-function-call-with-signature/5")
 2321     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-call-with-literal-arg/6")
 2322     (check-next-stream-line-equal _test-output-stream "    (do-add 3 4)"        "F - test-convert-function-call-with-signature/6")
 2323     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/8")
 2324     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-function-with-local-var-in-reg/9")
 2325     (check-next-stream-line-equal _test-output-stream "    e9/jump $main:0x00000001:break/disp32"  "F - test-convert-function-call-with-literal-arg/10")
 2326     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-signature/7")
 2327     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:break:" "F - test-convert-function-call-with-signature/8")
 2328     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-signature/9")
 2329     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-signature/10")
 2330     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-signature/11")
 2331     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-signature/12")
 2332     # . epilogue
 2333     89/<- %esp 5/r32/ebp
 2334     5d/pop-to-ebp
 2335     c3/return
 2336 
 2337 test-convert-function-with-local-var-in-mem:
 2338     # . prologue
 2339     55/push-ebp
 2340     89/<- %ebp 4/r32/esp
 2341     # setup
 2342     (clear-stream _test-input-stream)
 2343     (clear-stream $_test-input-buffered-file->buffer)
 2344     (clear-stream _test-output-stream)
 2345     (clear-stream $_test-output-buffered-file->buffer)
 2346     #
 2347     (write _test-input-stream "fn foo {\n")
 2348     (write _test-input-stream "  var x: int\n")
 2349     (write _test-input-stream "  increment x\n")
 2350     (write _test-input-stream "}\n")
 2351     # convert
 2352     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2353     (flush _test-output-buffered-file)
 2354 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2360     # check output
 2361     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-mem/0")
 2362     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-mem/1")
 2363     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-mem/2")
 2364     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-mem/3")
 2365     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-mem/4")
 2366     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-mem/5")
 2367     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-in-mem/6")
 2368     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-local-var-in-mem/7")
 2369     (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")
 2370     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-mem/9")
 2371     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-mem/10")
 2372     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-mem/11")
 2373     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-mem/12")
 2374     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-mem/13")
 2375     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-mem/14")
 2376     # . epilogue
 2377     89/<- %esp 5/r32/ebp
 2378     5d/pop-to-ebp
 2379     c3/return
 2380 
 2381 test-convert-invalid-literal:
 2382     # . prologue
 2383     55/push-ebp
 2384     89/<- %ebp 4/r32/esp
 2385     # setup
 2386     (clear-stream _test-input-stream)
 2387     (clear-stream $_test-input-buffered-file->buffer)
 2388     (clear-stream _test-output-stream)
 2389     (clear-stream $_test-output-buffered-file->buffer)
 2390     (clear-stream _test-error-stream)
 2391     (clear-stream $_test-error-buffered-file->buffer)
 2392     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2393     68/push 0/imm32
 2394     68/push 0/imm32
 2395     89/<- %edx 4/r32/esp
 2396     (tailor-exit-descriptor %edx 0x10)
 2397     #
 2398     (write _test-input-stream "fn foo {\n")
 2399     (write _test-input-stream "  increment 1n\n")
 2400     (write _test-input-stream "}\n")
 2401     # convert
 2402     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2403     # registers except esp clobbered at this point
 2404     # restore ed
 2405     89/<- %edx 4/r32/esp
 2406     (flush _test-output-buffered-file)
 2407     (flush _test-error-buffered-file)
 2408 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2414     # check output
 2415     (check-stream-equal _test-output-stream  ""  "F - test-convert-invalid-literal: output should be empty")
 2416     (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")
 2417     # check that stop(1) was called
 2418     (check-ints-equal *(edx+4) 2 "F - test-convert-invalid-literal: exit status")
 2419     # don't restore from ebp
 2420     81 0/subop/add %esp 8/imm32
 2421     # . epilogue
 2422     5d/pop-to-ebp
 2423     c3/return
 2424 
 2425 test-convert-valid-literal-with-metadata:
 2426     # . prologue
 2427     55/push-ebp
 2428     89/<- %ebp 4/r32/esp
 2429     # setup
 2430     (clear-stream _test-input-stream)
 2431     (clear-stream $_test-input-buffered-file->buffer)
 2432     (clear-stream _test-output-stream)
 2433     (clear-stream $_test-output-buffered-file->buffer)
 2434     #
 2435     (write _test-input-stream "fn foo {\n")
 2436     (write _test-input-stream "  var x/eax: int <- copy 1/abc\n")
 2437     (write _test-input-stream "}\n")
 2438     # convert
 2439     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2440     (flush _test-output-buffered-file)
 2441 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2447     # no errors
 2448     # . epilogue
 2449     89/<- %esp 5/r32/ebp
 2450     5d/pop-to-ebp
 2451     c3/return
 2452 
 2453 test-local-var-in-mem-has-no-initializer:
 2454     # . prologue
 2455     55/push-ebp
 2456     89/<- %ebp 4/r32/esp
 2457     # setup
 2458     (clear-stream _test-input-stream)
 2459     (clear-stream $_test-input-buffered-file->buffer)
 2460     (clear-stream _test-output-stream)
 2461     (clear-stream $_test-output-buffered-file->buffer)
 2462     (clear-stream _test-error-stream)
 2463     (clear-stream $_test-error-buffered-file->buffer)
 2464     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2465     68/push 0/imm32
 2466     68/push 0/imm32
 2467     89/<- %edx 4/r32/esp
 2468     (tailor-exit-descriptor %edx 0x10)
 2469     #
 2470     (write _test-input-stream "fn foo {\n")
 2471     (write _test-input-stream "  var x: int <- copy 0\n")
 2472     (write _test-input-stream "  increment x\n")
 2473     (write _test-input-stream "}\n")
 2474     # convert
 2475     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2476     # registers except esp clobbered at this point
 2477     # restore ed
 2478     89/<- %edx 4/r32/esp
 2479     (flush _test-output-buffered-file)
 2480     (flush _test-error-buffered-file)
 2481 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2487     # check output
 2488     (check-stream-equal _test-output-stream  ""  "F - test-var-in-mem-has-no-initializer: output should be empty")
 2489     (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")
 2490     # check that stop(1) was called
 2491     (check-ints-equal *(edx+4) 2 "F - test-var-in-mem-has-no-initializer: exit status")
 2492     # don't restore from ebp
 2493     81 0/subop/add %esp 8/imm32
 2494     # . epilogue
 2495     5d/pop-to-ebp
 2496     c3/return
 2497 
 2498 test-convert-function-with-local-var-with-compound-type-in-mem:
 2499     # . prologue
 2500     55/push-ebp
 2501     89/<- %ebp 4/r32/esp
 2502     # setup
 2503     (clear-stream _test-input-stream)
 2504     (clear-stream $_test-input-buffered-file->buffer)
 2505     (clear-stream _test-output-stream)
 2506     (clear-stream $_test-output-buffered-file->buffer)
 2507     #
 2508     (write _test-input-stream "fn foo {\n")
 2509     (write _test-input-stream "  var x: (addr int)\n")
 2510     (write _test-input-stream "  copy-to x, 0\n")
 2511     (write _test-input-stream "}\n")
 2512     # convert
 2513     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2514     (flush _test-output-buffered-file)
 2515 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2521     # check output
 2522     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-with-compound-type-in-mem/0")
 2523     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-with-compound-type-in-mem/1")
 2524     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-with-compound-type-in-mem/2")
 2525     (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")
 2526     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-with-compound-type-in-mem/4")
 2527     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-with-compound-type-in-mem/5")
 2528     (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")
 2529     (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")
 2530     (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")
 2531     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-with-compound-type-in-mem/9")
 2532     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-with-compound-type-in-mem/10")
 2533     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-with-compound-type-in-mem/11")
 2534     (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")
 2535     (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")
 2536     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-with-compound-type-in-mem/14")
 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-reg:
 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 "  var x/ecx: int <- copy 3\n")
 2554     (write _test-input-stream "  x <- increment\n")
 2555     (write _test-input-stream "}\n")
 2556     # convert
 2557     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2558     (flush _test-output-buffered-file)
 2559 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2565     # check output
 2566     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-reg/0")
 2567     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-reg/1")
 2568     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-reg/2")
 2569     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-reg/3")
 2570     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-reg/4")
 2571     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-reg/5")
 2572     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-local-var-in-reg/6")
 2573     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-convert-function-with-local-var-in-reg/7")
 2574     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-convert-function-with-local-var-in-reg/8")
 2575     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-local-var-in-reg/9")
 2576     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-reg/10")
 2577     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-reg/11")
 2578     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-reg/12")
 2579     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-reg/13")
 2580     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-reg/14")
 2581     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-reg/15")
 2582     # . epilogue
 2583     89/<- %esp 5/r32/ebp
 2584     5d/pop-to-ebp
 2585     c3/return
 2586 
 2587 test-convert-function-with-local-var-in-same-reg:
 2588     # . prologue
 2589     55/push-ebp
 2590     89/<- %ebp 4/r32/esp
 2591     # setup
 2592     (clear-stream _test-input-stream)
 2593     (clear-stream $_test-input-buffered-file->buffer)
 2594     (clear-stream _test-output-stream)
 2595     (clear-stream $_test-output-buffered-file->buffer)
 2596     #
 2597     (write _test-input-stream "fn foo {\n")
 2598     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 2599     (write _test-input-stream "  var y/ecx: int <- copy x\n")
 2600     (write _test-input-stream "}\n")
 2601     # convert
 2602     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2603     (flush _test-output-buffered-file)
 2604 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2610     # check output
 2611     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-same-reg/0")
 2612     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-same-reg/1")
 2613     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-same-reg/2")
 2614     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-same-reg/3")
 2615     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-same-reg/4")
 2616     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-same-reg/5")
 2617     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-local-var-in-same-reg/6")
 2618     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-convert-function-with-local-var-in-same-reg/7")
 2619     # optimization: skip the second copy
 2620     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-local-var-in-same-reg/8")
 2621     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-same-reg/9")
 2622     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-same-reg/10")
 2623     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-same-reg/11")
 2624     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-same-reg/12")
 2625     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-same-reg/13")
 2626     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-same-reg/14")
 2627     # . epilogue
 2628     89/<- %esp 5/r32/ebp
 2629     5d/pop-to-ebp
 2630     c3/return
 2631 
 2632 test-convert-function-with-local-var-in-same-reg-dereferenced:
 2633     # . prologue
 2634     55/push-ebp
 2635     89/<- %ebp 4/r32/esp
 2636     # setup
 2637     (clear-stream _test-input-stream)
 2638     (clear-stream $_test-input-buffered-file->buffer)
 2639     (clear-stream _test-output-stream)
 2640     (clear-stream $_test-output-buffered-file->buffer)
 2641     #
 2642     (write _test-input-stream "fn foo {\n")
 2643     (write _test-input-stream "  var x/ecx: (addr int) <- copy 0\n")
 2644     (write _test-input-stream "  var y/ecx: int <- copy *x\n")
 2645     (write _test-input-stream "}\n")
 2646     # convert
 2647     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2648     (flush _test-output-buffered-file)
 2649 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2655     # check output
 2656     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-same-reg-dereferenced/0")
 2657     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-same-reg-dereferenced/1")
 2658     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-same-reg-dereferenced/2")
 2659     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-same-reg-dereferenced/3")
 2660     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-same-reg-dereferenced/4")
 2661     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-same-reg-dereferenced/5")
 2662     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-local-var-in-same-reg-dereferenced/6")
 2663     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-function-with-local-var-in-same-reg-dereferenced/7")
 2664     (check-next-stream-line-equal _test-output-stream "    8b/-> *ecx 0x00000001/r32"  "F - test-convert-function-with-local-var-in-same-reg-dereferenced/8")  # don't optimize this away
 2665     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-local-var-in-same-reg-dereferenced/9")
 2666     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-same-reg-dereferenced/10")
 2667     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-same-reg-dereferenced/11")
 2668     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-same-reg-dereferenced/12")
 2669     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-same-reg-dereferenced/13")
 2670     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-same-reg-dereferenced/14")
 2671     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-same-reg-dereferenced/15")
 2672     # . epilogue
 2673     89/<- %esp 5/r32/ebp
 2674     5d/pop-to-ebp
 2675     c3/return
 2676 
 2677 test-float-var-in-wrong-register:
 2678     # . prologue
 2679     55/push-ebp
 2680     89/<- %ebp 4/r32/esp
 2681     # setup
 2682     (clear-stream _test-input-stream)
 2683     (clear-stream $_test-input-buffered-file->buffer)
 2684     (clear-stream _test-output-stream)
 2685     (clear-stream $_test-output-buffered-file->buffer)
 2686     (clear-stream _test-error-stream)
 2687     (clear-stream $_test-error-buffered-file->buffer)
 2688     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2689     68/push 0/imm32
 2690     68/push 0/imm32
 2691     89/<- %edx 4/r32/esp
 2692     (tailor-exit-descriptor %edx 0x10)
 2693     #
 2694     (write _test-input-stream "fn foo {\n")
 2695     (write _test-input-stream "  var x/eax: int <- copy 0\n")
 2696     (write _test-input-stream "  var y/eax: float <- convert x\n")
 2697     (write _test-input-stream "}\n")
 2698     # convert
 2699     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2700     # registers except esp clobbered at this point
 2701     # restore ed
 2702     89/<- %edx 4/r32/esp
 2703     (flush _test-output-buffered-file)
 2704     (flush _test-error-buffered-file)
 2705 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2711     # check output
 2712     (check-stream-equal _test-output-stream  ""  "F - test-float-var-in-wrong-register: output should be empty")
 2713     (check-next-stream-line-equal _test-error-stream  "fn foo: float var 'y' should be in a floating-point register"  "F - test-float-var-in-wrong-register: error message")
 2714     # check that stop(1) was called
 2715     (check-ints-equal *(edx+4) 2 "F - test-float-var-in-wrong-register: exit status")
 2716     # don't restore from ebp
 2717     81 0/subop/add %esp 8/imm32
 2718     # . epilogue
 2719     5d/pop-to-ebp
 2720     c3/return
 2721 
 2722 test-non-float-var-in-wrong-register:
 2723     # . prologue
 2724     55/push-ebp
 2725     89/<- %ebp 4/r32/esp
 2726     # setup
 2727     (clear-stream _test-input-stream)
 2728     (clear-stream $_test-input-buffered-file->buffer)
 2729     (clear-stream _test-output-stream)
 2730     (clear-stream $_test-output-buffered-file->buffer)
 2731     (clear-stream _test-error-stream)
 2732     (clear-stream $_test-error-buffered-file->buffer)
 2733     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2734     68/push 0/imm32
 2735     68/push 0/imm32
 2736     89/<- %edx 4/r32/esp
 2737     (tailor-exit-descriptor %edx 0x10)
 2738     #
 2739     (write _test-input-stream "fn foo {\n")
 2740     (write _test-input-stream "  var x/xmm5: int <- copy 0\n")
 2741     (write _test-input-stream "}\n")
 2742     # convert
 2743     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2744     # registers except esp clobbered at this point
 2745     # restore ed
 2746     89/<- %edx 4/r32/esp
 2747     (flush _test-output-buffered-file)
 2748     (flush _test-error-buffered-file)
 2749 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2755     # check output
 2756     (check-stream-equal _test-output-stream  ""  "F - test-non-float-var-in-wrong-register: output should be empty")
 2757     (check-next-stream-line-equal _test-error-stream  "fn foo: non-float var 'x' should be in an integer register"  "F - test-non-float-var-in-wrong-register: error message")
 2758     # check that stop(1) was called
 2759     (check-ints-equal *(edx+4) 2 "F - test-non-float-var-in-wrong-register: exit status")
 2760     # don't restore from ebp
 2761     81 0/subop/add %esp 8/imm32
 2762     # . epilogue
 2763     5d/pop-to-ebp
 2764     c3/return
 2765 
 2766 test-convert-function-with-allocate:
 2767     # . prologue
 2768     55/push-ebp
 2769     89/<- %ebp 4/r32/esp
 2770     # setup
 2771     (clear-stream _test-input-stream)
 2772     (clear-stream $_test-input-buffered-file->buffer)
 2773     (clear-stream _test-output-stream)
 2774     (clear-stream $_test-output-buffered-file->buffer)
 2775     #
 2776     (write _test-input-stream "fn foo {\n")
 2777     (write _test-input-stream "  var x/ecx: (addr handle int) <- copy 0\n")
 2778     (write _test-input-stream "  allocate x\n")
 2779     (write _test-input-stream "}\n")
 2780     # convert
 2781     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2782     (flush _test-output-buffered-file)
 2783 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2789     # check output
 2790     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-allocate/0")
 2791     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-allocate/1")
 2792     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-allocate/2")
 2793     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-allocate/3")
 2794     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-allocate/4")
 2795     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-allocate/5")
 2796     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-allocate/6")
 2797     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-function-with-allocate/7")
 2798     (check-next-stream-line-equal _test-output-stream "    (allocate Heap 0x00000004 %ecx)"  "F - test-convert-function-with-allocate/8")  # 4 = size-of(int)
 2799     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-allocate/9")
 2800     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-allocate/10")
 2801     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-allocate/11")
 2802     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-allocate/12")
 2803     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-allocate/13")
 2804     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-allocate/14")
 2805     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-allocate/15")
 2806     # . epilogue
 2807     89/<- %esp 5/r32/ebp
 2808     5d/pop-to-ebp
 2809     c3/return
 2810 
 2811 test-initializer-in-hex:
 2812     # . prologue
 2813     55/push-ebp
 2814     89/<- %ebp 4/r32/esp
 2815     # setup
 2816     (clear-stream _test-input-stream)
 2817     (clear-stream $_test-input-buffered-file->buffer)
 2818     (clear-stream _test-output-stream)
 2819     (clear-stream $_test-output-buffered-file->buffer)
 2820     (clear-stream _test-error-stream)
 2821     (clear-stream $_test-error-buffered-file->buffer)
 2822     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2823     68/push 0/imm32
 2824     68/push 0/imm32
 2825     89/<- %edx 4/r32/esp
 2826     (tailor-exit-descriptor %edx 0x10)
 2827     #
 2828     (write _test-input-stream "fn foo {\n")
 2829     (write _test-input-stream "  var x/ecx: int <- copy 10\n")
 2830     (write _test-input-stream "}\n")
 2831     # convert
 2832     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2833     # registers except esp clobbered at this point
 2834     # restore ed
 2835     89/<- %edx 4/r32/esp
 2836     (flush _test-output-buffered-file)
 2837     (flush _test-error-buffered-file)
 2838 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2844     # check output
 2845     (check-stream-equal _test-output-stream  ""  "F - test-initializer-in-hex: output should be empty")
 2846     (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")
 2847     # check that stop(1) was called
 2848     (check-ints-equal *(edx+4) 2 "F - test-initializer-in-hex: exit status")
 2849     # don't restore from ebp
 2850     81 0/subop/add %esp 8/imm32
 2851     # . epilogue
 2852     5d/pop-to-ebp
 2853     c3/return
 2854 
 2855 test-convert-function-with-second-local-var-in-same-reg:
 2856     # . prologue
 2857     55/push-ebp
 2858     89/<- %ebp 4/r32/esp
 2859     # setup
 2860     (clear-stream _test-input-stream)
 2861     (clear-stream $_test-input-buffered-file->buffer)
 2862     (clear-stream _test-output-stream)
 2863     (clear-stream $_test-output-buffered-file->buffer)
 2864     #
 2865     (write _test-input-stream "fn foo {\n")
 2866     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 2867     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
 2868     (write _test-input-stream "  y <- increment\n")
 2869     (write _test-input-stream "}\n")
 2870     # convert
 2871     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2872     (flush _test-output-buffered-file)
 2873 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2879     # check output
 2880     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-second-local-var-in-same-reg/0")
 2881     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-second-local-var-in-same-reg/1")
 2882     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-second-local-var-in-same-reg/2")
 2883     (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")
 2884     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-second-local-var-in-same-reg/4")
 2885     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-second-local-var-in-same-reg/5")
 2886     (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")
 2887     (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")
 2888     (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")
 2889     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-convert-function-with-second-local-var-in-same-reg/9")
 2890     (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")
 2891     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-second-local-var-in-same-reg/11")
 2892     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-second-local-var-in-same-reg/12")
 2893     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-second-local-var-in-same-reg/13")
 2894     (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")
 2895     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-second-local-var-in-same-reg/15")
 2896     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-second-local-var-in-same-reg/16")
 2897     # . epilogue
 2898     89/<- %esp 5/r32/ebp
 2899     5d/pop-to-ebp
 2900     c3/return
 2901 
 2902 test-read-clobbered-reg-var:
 2903     # . prologue
 2904     55/push-ebp
 2905     89/<- %ebp 4/r32/esp
 2906     # setup
 2907     (clear-stream _test-input-stream)
 2908     (clear-stream $_test-input-buffered-file->buffer)
 2909     (clear-stream _test-output-stream)
 2910     (clear-stream $_test-output-buffered-file->buffer)
 2911     (clear-stream _test-error-stream)
 2912     (clear-stream $_test-error-buffered-file->buffer)
 2913     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)  # bytes of args in call to convert-mu
 2914     68/push 0/imm32
 2915     68/push 0/imm32
 2916     89/<- %edx 4/r32/esp
 2917     (tailor-exit-descriptor %edx 0x10)
 2918     #
 2919     (write _test-input-stream "fn foo {\n")
 2920     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 2921     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
 2922     (write _test-input-stream "  x <- increment\n")
 2923     (write _test-input-stream "}\n")
 2924     # convert
 2925     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2926     # registers except esp clobbered at this point
 2927     # restore ed
 2928     89/<- %edx 4/r32/esp
 2929     (flush _test-output-buffered-file)
 2930     (flush _test-error-buffered-file)
 2931 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2937     # check output
 2938     (check-stream-equal _test-output-stream  ""  "F - test-read-clobbered-reg-var: output should be empty")
 2939     (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")
 2940     # check that stop(1) was called
 2941     (check-ints-equal *(edx+4) 2 "F - test-read-clobbered-reg-var: exit status")
 2942     # don't restore from ebp
 2943     81 0/subop/add %esp 8/imm32
 2944     # . epilogue
 2945     5d/pop-to-ebp
 2946     c3/return
 2947 
 2948 test-overlapping-int-fp-registers:
 2949     # . prologue
 2950     55/push-ebp
 2951     89/<- %ebp 4/r32/esp
 2952     # setup
 2953     (clear-stream _test-input-stream)
 2954     (clear-stream $_test-input-buffered-file->buffer)
 2955     (clear-stream _test-output-stream)
 2956     (clear-stream $_test-output-buffered-file->buffer)
 2957     (clear-stream _test-error-stream)
 2958     (clear-stream $_test-error-buffered-file->buffer)
 2959     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)  # bytes of args in call to convert-mu
 2960     68/push 0/imm32
 2961     68/push 0/imm32
 2962     89/<- %edx 4/r32/esp
 2963     (tailor-exit-descriptor %edx 0x10)
 2964     #
 2965     (write _test-input-stream "fn foo {\n")
 2966     (write _test-input-stream "  var x/eax: int <- copy 3\n")
 2967     (write _test-input-stream "  var y/xmm0: float <- convert x\n")
 2968     (write _test-input-stream "  x <- increment\n")
 2969     (write _test-input-stream "}\n")
 2970     # convert
 2971     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2972     # registers except esp clobbered at this point
 2973     # restore ed
 2974     89/<- %edx 4/r32/esp
 2975     (flush _test-output-buffered-file)
 2976     (flush _test-error-buffered-file)
 2977 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2983     # no errors
 2984     (check-next-stream-line-equal _test-error-stream  ""  "F - test-overlapping-int-fp-registers: error message")
 2985     # don't bother checking the generated code
 2986     # don't restore from ebp
 2987     81 0/subop/add %esp 8/imm32
 2988     # . epilogue
 2989     5d/pop-to-ebp
 2990     c3/return
 2991 
 2992 test-convert-function-call:
 2993     # . prologue
 2994     55/push-ebp
 2995     89/<- %ebp 4/r32/esp
 2996     # setup
 2997     (clear-stream _test-input-stream)
 2998     (clear-stream $_test-input-buffered-file->buffer)
 2999     (clear-stream _test-output-stream)
 3000     (clear-stream $_test-output-buffered-file->buffer)
 3001     #
 3002     (write _test-input-stream "fn main -> _/ebx: int {\n")
 3003     (write _test-input-stream "  var result/ebx: int <- foo\n")
 3004     (write _test-input-stream "  return result\n")
 3005     (write _test-input-stream "}\n")
 3006     (write _test-input-stream "fn foo -> _/ebx: int {\n")
 3007     (write _test-input-stream "  var result/ebx: int <- copy 3\n")
 3008     (write _test-input-stream "  return result\n")
 3009     (write _test-input-stream "}\n")
 3010     # convert
 3011     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3012     (flush _test-output-buffered-file)
 3013 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 3019     # check output
 3020     (check-next-stream-line-equal _test-output-stream "main:"                   "F - test-convert-function-call/0")
 3021     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call/1")
 3022     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call/2")
 3023     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call/3")
 3024     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call/4")
 3025     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:loop:"  "F - test-convert-function-call/5")
 3026     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ebx"  "F - test-convert-function-call-with-literal-arg/6")
 3027     (check-next-stream-line-equal _test-output-stream "    (foo)"               "F - test-convert-function-call/6")
 3028     (check-next-stream-line-equal _test-output-stream "    8b/-> %ebx 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/8")
 3029     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-call-with-literal-arg/27")
 3030     (check-next-stream-line-equal _test-output-stream "    e9/jump $main:0x00000001:break/disp32"  "F - test-convert-function-call-with-literal-arg/10")
 3031     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call/7")
 3032     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:break:" "F - test-convert-function-call/8")
 3033     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call/9")
 3034     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call/10")
 3035     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call/11")
 3036     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call/12")
 3037     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call/13")
 3038     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call/14")
 3039     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call/15")
 3040     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call/16")
 3041     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call/17")
 3042     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"  "F - test-convert-function-call/18")
 3043     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ebx"  "F - test-convert-function-call-with-literal-arg/6")
 3044     (check-next-stream-line-equal _test-output-stream "    bb/copy-to-ebx 3/imm32"  "F - test-convert-function-call/19")
 3045     (check-next-stream-line-equal _test-output-stream "    8b/-> %ebx 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/8")
 3046     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-call-with-literal-arg/27")
 3047     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-call-with-literal-arg/10")
 3048     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call/20")
 3049     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-call/21")
 3050     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call/22")
 3051     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call/23")
 3052     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call/24")
 3053     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call/25")
 3054     # . epilogue
 3055     89/<- %esp 5/r32/ebp
 3056     5d/pop-to-ebp
 3057     c3/return
 3058 
 3059 test-convert-function-call-with-inout-with-compound-type:
 3060     # . prologue
 3061     55/push-ebp
 3062     89/<- %ebp 4/r32/esp
 3063     # setup
 3064     (clear-stream _test-input-stream)
 3065     (clear-stream $_test-input-buffered-file->buffer)
 3066     (clear-stream _test-output-stream)
 3067     (clear-stream $_test-output-buffered-file->buffer)
 3068     #
 3069     (write _test-input-stream "fn f {\n")
 3070     (write _test-input-stream "  var x: (addr int)\n")
 3071     (write _test-input-stream "  g x\n")
 3072     (write _test-input-stream "}\n")
 3073     (write _test-input-stream "fn g a: (addr int) {\n")
 3074     (write _test-input-stream "}\n")
 3075     # convert
 3076     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3077     (flush _test-output-buffered-file)
 3078 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 3084     # check output
 3085     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-inout-with-compound-type/0")
 3086     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-inout-with-compound-type/1")
 3087     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-inout-with-compound-type/2")
 3088     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-inout-with-compound-type/3")
 3089     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-inout-with-compound-type/4")
 3090     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"     "F - test-convert-function-call-with-inout-with-compound-type/5")
 3091     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-call-with-inout-with-compound-type/6")
 3092     (check-next-stream-line-equal _test-output-stream "    (g *(ebp+0xfffffffc))"  "F - test-convert-function-call-with-inout-with-compound-type/7")
 3093     (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")
 3094     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-inout-with-compound-type/9")
 3095     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"    "F - test-convert-function-call-with-inout-with-compound-type/10")
 3096     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-inout-with-compound-type/11")
 3097     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-inout-with-compound-type/12")
 3098     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-inout-with-compound-type/13")
 3099     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-inout-with-compound-type/14")
 3100     (check-next-stream-line-equal _test-output-stream "g:"                      "F - test-convert-function-call-with-inout-with-compound-type/15")
 3101     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-inout-with-compound-type/16")
 3102     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-inout-with-compound-type/17")
 3103     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-inout-with-compound-type/18")
 3104     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-inout-with-compound-type/19")
 3105     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-inout-with-compound-type/20")
 3106     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-inout-with-compound-type/21")
 3107     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-inout-with-compound-type/22")
 3108     # . epilogue
 3109     89/<- %esp 5/r32/ebp
 3110     5d/pop-to-ebp
 3111     c3/return
 3112 
 3113 test-convert-function-call-with-inout-with-type-parameter:
 3114     # . prologue
 3115     55/push-ebp
 3116     89/<- %ebp 4/r32/esp
 3117     # setup
 3118     (clear-stream _test-input-stream)
 3119     (clear-stream $_test-input-buffered-file->buffer)
 3120     (clear-stream _test-output-stream)
 3121     (clear-stream $_test-output-buffered-file->buffer)
 3122     (clear-stream _test-error-stream)
 3123     (clear-stream $_test-error-buffered-file->buffer)
 3124     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3125     68/push 0/imm32
 3126     68/push 0/imm32
 3127     89/<- %edx 4/r32/esp
 3128     (tailor-exit-descriptor %edx 0x10)
 3129     #
 3130     (write _test-input-stream "fn f {\n")
 3131     (write _test-input-stream "  var x: (addr int)\n")
 3132     (write _test-input-stream "  g x\n")
 3133     (write _test-input-stream "}\n")
 3134     (write _test-input-stream "fn g a: (addr _) {\n")
 3135     (write _test-input-stream "}\n")
 3136     # convert
 3137     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3138     # registers except esp clobbered at this point
 3139     # restore ed
 3140     89/<- %edx 4/r32/esp
 3141     (flush _test-output-buffered-file)
 3142     (flush _test-error-buffered-file)
 3143 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3149     # no error; types matched
 3150     (check-stream-equal _test-error-stream  ""  "F - test-convert-function-call-with-inout-with-type-parameter: error stream should be empty")
 3151     # don't bother checking the generated code; that's in the test 'test-local-clobbered-by-fn-output' below
 3152     # don't restore from ebp
 3153     81 0/subop/add %esp 8/imm32
 3154     # . epilogue
 3155     5d/pop-to-ebp
 3156     c3/return
 3157 
 3158 test-convert-function-call-with-incorrect-inout-type:
 3159     # . prologue
 3160     55/push-ebp
 3161     89/<- %ebp 4/r32/esp
 3162     # setup
 3163     (clear-stream _test-input-stream)
 3164     (clear-stream $_test-input-buffered-file->buffer)
 3165     (clear-stream _test-output-stream)
 3166     (clear-stream $_test-output-buffered-file->buffer)
 3167     (clear-stream _test-error-stream)
 3168     (clear-stream $_test-error-buffered-file->buffer)
 3169     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3170     68/push 0/imm32
 3171     68/push 0/imm32
 3172     89/<- %edx 4/r32/esp
 3173     (tailor-exit-descriptor %edx 0x10)
 3174     #
 3175     (write _test-input-stream "fn f {\n")
 3176     (write _test-input-stream "  var x: int\n")
 3177     (write _test-input-stream "  g x\n")
 3178     (write _test-input-stream "}\n")
 3179     (write _test-input-stream "fn g a: foo {\n")
 3180     (write _test-input-stream "}\n")
 3181     # convert
 3182     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3183     # registers except esp clobbered at this point
 3184     # restore ed
 3185     89/<- %edx 4/r32/esp
 3186     (flush _test-output-buffered-file)
 3187     (flush _test-error-buffered-file)
 3188 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3194     # check output
 3195     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-incorrect-inout-type: output should be empty")
 3196     (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")
 3197     # check that stop(1) was called
 3198     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-incorrect-inout-type: exit status")
 3199     # don't restore from ebp
 3200     81 0/subop/add %esp 8/imm32
 3201     5d/pop-to-ebp
 3202     c3/return
 3203 
 3204 test-convert-function-call-with-inout-with-incorrect-compound-type:
 3205     # . prologue
 3206     55/push-ebp
 3207     89/<- %ebp 4/r32/esp
 3208     # setup
 3209     (clear-stream _test-input-stream)
 3210     (clear-stream $_test-input-buffered-file->buffer)
 3211     (clear-stream _test-output-stream)
 3212     (clear-stream $_test-output-buffered-file->buffer)
 3213     (clear-stream _test-error-stream)
 3214     (clear-stream $_test-error-buffered-file->buffer)
 3215     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3216     68/push 0/imm32
 3217     68/push 0/imm32
 3218     89/<- %edx 4/r32/esp
 3219     (tailor-exit-descriptor %edx 0x10)
 3220     #
 3221     (write _test-input-stream "fn f {\n")
 3222     (write _test-input-stream "  var x: (addr int)\n")
 3223     (write _test-input-stream "  g x\n")
 3224     (write _test-input-stream "}\n")
 3225     (write _test-input-stream "fn g a: (addr bool) {\n")
 3226     (write _test-input-stream "}\n")
 3227     # convert
 3228     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3229     # registers except esp clobbered at this point
 3230     # restore ed
 3231     89/<- %edx 4/r32/esp
 3232     (flush _test-output-buffered-file)
 3233     (flush _test-error-buffered-file)
 3234 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3240     # check output
 3241     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-inout-with-incorrect-compound-type: output should be empty")
 3242     (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")
 3243     # don't restore from ebp
 3244     81 0/subop/add %esp 8/imm32
 3245     # . epilogue
 3246     5d/pop-to-ebp
 3247     c3/return
 3248 
 3249 test-convert-function-call-with-inout-with-multiple-type-parameters:
 3250     # . prologue
 3251     55/push-ebp
 3252     89/<- %ebp 4/r32/esp
 3253     # setup
 3254     (clear-stream _test-input-stream)
 3255     (clear-stream $_test-input-buffered-file->buffer)
 3256     (clear-stream _test-output-stream)
 3257     (clear-stream $_test-output-buffered-file->buffer)
 3258     (clear-stream _test-error-stream)
 3259     (clear-stream $_test-error-buffered-file->buffer)
 3260     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3261     68/push 0/imm32
 3262     68/push 0/imm32
 3263     89/<- %edx 4/r32/esp
 3264     (tailor-exit-descriptor %edx 0x10)
 3265     #
 3266     (write _test-input-stream "fn f {\n")
 3267     (write _test-input-stream "  var x: (addr int)\n")
 3268     (write _test-input-stream "  var y: (addr int)\n")
 3269     (write _test-input-stream "  g x, y\n")
 3270     (write _test-input-stream "}\n")
 3271     (write _test-input-stream "fn g a: (addr _), b: (addr _) {\n")
 3272     (write _test-input-stream "}\n")
 3273     # convert
 3274     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3275     # registers except esp clobbered at this point
 3276     # restore ed
 3277     89/<- %edx 4/r32/esp
 3278     (flush _test-output-buffered-file)
 3279     (flush _test-error-buffered-file)
 3280 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3286     # no errors
 3287     (check-stream-equal _test-error-stream  ""  "F - test-convert-function-call-with-inout-with-multiple-type-parameters: error stream should be empty")
 3288     # don't bother checking the generated code
 3289     # don't restore from ebp
 3290     81 0/subop/add %esp 8/imm32
 3291     # . epilogue
 3292     5d/pop-to-ebp
 3293     c3/return
 3294 
 3295 test-type-parameter-matches-rest-of-type:
 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     (clear-stream _test-error-stream)
 3305     (clear-stream $_test-error-buffered-file->buffer)
 3306     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3307     68/push 0/imm32
 3308     68/push 0/imm32
 3309     89/<- %edx 4/r32/esp
 3310     (tailor-exit-descriptor %edx 0x10)
 3311     #
 3312     (write _test-input-stream "fn f {\n")
 3313     (write _test-input-stream "  var x: (addr array int)\n")
 3314     (write _test-input-stream "  g x\n")
 3315     (write _test-input-stream "}\n")
 3316     (write _test-input-stream "fn g a: (addr _) {\n")
 3317     (write _test-input-stream "}\n")
 3318     # convert
 3319     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3320     # registers except esp clobbered at this point
 3321     # restore ed
 3322     89/<- %edx 4/r32/esp
 3323     (flush _test-output-buffered-file)
 3324     (flush _test-error-buffered-file)
 3325 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3331     # no errors
 3332     (check-stream-equal _test-error-stream  ""  "F - test-type-parameter-matches-rest-of-type: error stream should be empty")
 3333     # don't bother checking the generated code
 3334     # don't restore from ebp
 3335     81 0/subop/add %esp 8/imm32
 3336     # . epilogue
 3337     5d/pop-to-ebp
 3338     c3/return
 3339 
 3340 test-convert-function-call-with-inout-with-incompatible-type-parameters:
 3341     # . prologue
 3342     55/push-ebp
 3343     89/<- %ebp 4/r32/esp
 3344     # setup
 3345     (clear-stream _test-input-stream)
 3346     (clear-stream $_test-input-buffered-file->buffer)
 3347     (clear-stream _test-output-stream)
 3348     (clear-stream $_test-output-buffered-file->buffer)
 3349     (clear-stream _test-error-stream)
 3350     (clear-stream $_test-error-buffered-file->buffer)
 3351     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3352     68/push 0/imm32
 3353     68/push 0/imm32
 3354     89/<- %edx 4/r32/esp
 3355     (tailor-exit-descriptor %edx 0x10)
 3356     #
 3357     (write _test-input-stream "fn f {\n")
 3358     (write _test-input-stream "  var x: (addr int)\n")
 3359     (write _test-input-stream "  var y: (addr boolean)\n")
 3360     (write _test-input-stream "  g x, y\n")
 3361     (write _test-input-stream "}\n")
 3362     (write _test-input-stream "fn g a: (addr _T), b: (addr _T) {\n")
 3363     (write _test-input-stream "}\n")
 3364     # convert
 3365     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3366     # registers except esp clobbered at this point
 3367     # restore ed
 3368     89/<- %edx 4/r32/esp
 3369     (flush _test-output-buffered-file)
 3370     (flush _test-error-buffered-file)
 3371 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3377     # check output
 3378     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-inout-with-incompatible-type-parameters: output should be empty")
 3379     (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")
 3380     # don't restore from ebp
 3381     81 0/subop/add %esp 8/imm32
 3382     # . epilogue
 3383     5d/pop-to-ebp
 3384     c3/return
 3385 
 3386 test-convert-function-call-with-too-few-inouts:
 3387     # . prologue
 3388     55/push-ebp
 3389     89/<- %ebp 4/r32/esp
 3390     # setup
 3391     (clear-stream _test-input-stream)
 3392     (clear-stream $_test-input-buffered-file->buffer)
 3393     (clear-stream _test-output-stream)
 3394     (clear-stream $_test-output-buffered-file->buffer)
 3395     (clear-stream _test-error-stream)
 3396     (clear-stream $_test-error-buffered-file->buffer)
 3397     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3398     68/push 0/imm32
 3399     68/push 0/imm32
 3400     89/<- %edx 4/r32/esp
 3401     (tailor-exit-descriptor %edx 0x10)
 3402     #
 3403     (write _test-input-stream "fn f {\n")
 3404     (write _test-input-stream "  g\n")
 3405     (write _test-input-stream "}\n")
 3406     (write _test-input-stream "fn g a: int {\n")
 3407     (write _test-input-stream "}\n")
 3408     # convert
 3409     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3410     # registers except esp clobbered at this point
 3411     # restore ed
 3412     89/<- %edx 4/r32/esp
 3413     (flush _test-output-buffered-file)
 3414     (flush _test-error-buffered-file)
 3415 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3421     # check output
 3422     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-few-inouts: output should be empty")
 3423     (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")
 3424     # check that stop(1) was called
 3425     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-few-inouts: exit status")
 3426     # don't restore from ebp
 3427     81 0/subop/add %esp 8/imm32
 3428     5d/pop-to-ebp
 3429     c3/return
 3430 
 3431 test-convert-function-call-with-too-many-inouts:
 3432     # . prologue
 3433     55/push-ebp
 3434     89/<- %ebp 4/r32/esp
 3435     # setup
 3436     (clear-stream _test-input-stream)
 3437     (clear-stream $_test-input-buffered-file->buffer)
 3438     (clear-stream _test-output-stream)
 3439     (clear-stream $_test-output-buffered-file->buffer)
 3440     (clear-stream _test-error-stream)
 3441     (clear-stream $_test-error-buffered-file->buffer)
 3442     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3443     68/push 0/imm32
 3444     68/push 0/imm32
 3445     89/<- %edx 4/r32/esp
 3446     (tailor-exit-descriptor %edx 0x10)
 3447     #
 3448     (write _test-input-stream "fn f {\n")
 3449     (write _test-input-stream "  var x: int\n")
 3450     (write _test-input-stream "  g x\n")
 3451     (write _test-input-stream "}\n")
 3452     (write _test-input-stream "fn g {\n")
 3453     (write _test-input-stream "}\n")
 3454     # convert
 3455     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3456     # registers except esp clobbered at this point
 3457     # restore ed
 3458     89/<- %edx 4/r32/esp
 3459     (flush _test-output-buffered-file)
 3460     (flush _test-error-buffered-file)
 3461 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3467     # check output
 3468     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-many-inouts: output should be empty")
 3469     (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")
 3470     # check that stop(1) was called
 3471     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-many-inouts: exit status")
 3472     # don't restore from ebp
 3473     81 0/subop/add %esp 8/imm32
 3474     5d/pop-to-ebp
 3475     c3/return
 3476 
 3477 test-convert-function-call-with-incorrect-output-type:
 3478     # . prologue
 3479     55/push-ebp
 3480     89/<- %ebp 4/r32/esp
 3481     # setup
 3482     (clear-stream _test-input-stream)
 3483     (clear-stream $_test-input-buffered-file->buffer)
 3484     (clear-stream _test-output-stream)
 3485     (clear-stream $_test-output-buffered-file->buffer)
 3486     (clear-stream _test-error-stream)
 3487     (clear-stream $_test-error-buffered-file->buffer)
 3488     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3489     68/push 0/imm32
 3490     68/push 0/imm32
 3491     89/<- %edx 4/r32/esp
 3492     (tailor-exit-descriptor %edx 0x10)
 3493     #
 3494     (write _test-input-stream "fn f {\n")
 3495     (write _test-input-stream "  var x/eax: int <- g\n")
 3496     (write _test-input-stream "}\n")
 3497     (write _test-input-stream "fn g -> _/eax: foo {\n")
 3498     (write _test-input-stream "}\n")
 3499     # convert
 3500     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3501     # registers except esp clobbered at this point
 3502     # restore ed
 3503     89/<- %edx 4/r32/esp
 3504     (flush _test-output-buffered-file)
 3505     (flush _test-error-buffered-file)
 3506 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3512     # check output
 3513     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-incorrect-output-type: output should be empty")
 3514     (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")
 3515     # check that stop(1) was called
 3516     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-incorrect-output-type: exit status")
 3517     # don't restore from ebp
 3518     81 0/subop/add %esp 8/imm32
 3519     5d/pop-to-ebp
 3520     c3/return
 3521 
 3522 test-convert-function-call-with-too-few-outputs:
 3523     # . prologue
 3524     55/push-ebp
 3525     89/<- %ebp 4/r32/esp
 3526     # setup
 3527     (clear-stream _test-input-stream)
 3528     (clear-stream $_test-input-buffered-file->buffer)
 3529     (clear-stream _test-output-stream)
 3530     (clear-stream $_test-output-buffered-file->buffer)
 3531     (clear-stream _test-error-stream)
 3532     (clear-stream $_test-error-buffered-file->buffer)
 3533     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3534     68/push 0/imm32
 3535     68/push 0/imm32
 3536     89/<- %edx 4/r32/esp
 3537     (tailor-exit-descriptor %edx 0x10)
 3538     #
 3539     (write _test-input-stream "fn f {\n")
 3540     (write _test-input-stream "  g\n")
 3541     (write _test-input-stream "}\n")
 3542     (write _test-input-stream "fn g -> _/eax: int {\n")
 3543     (write _test-input-stream "}\n")
 3544     # convert
 3545     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3546     # registers except esp clobbered at this point
 3547     # restore ed
 3548     89/<- %edx 4/r32/esp
 3549     (flush _test-output-buffered-file)
 3550     (flush _test-error-buffered-file)
 3551 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3557     # check output
 3558     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-few-outputs: output should be empty")
 3559     (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")
 3560     # check that stop(1) was called
 3561     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-few-outputs: exit status")
 3562     # don't restore from ebp
 3563     81 0/subop/add %esp 8/imm32
 3564     5d/pop-to-ebp
 3565     c3/return
 3566 
 3567 test-convert-function-call-with-too-many-outputs:
 3568     # . prologue
 3569     55/push-ebp
 3570     89/<- %ebp 4/r32/esp
 3571     # setup
 3572     (clear-stream _test-input-stream)
 3573     (clear-stream $_test-input-buffered-file->buffer)
 3574     (clear-stream _test-output-stream)
 3575     (clear-stream $_test-output-buffered-file->buffer)
 3576     (clear-stream _test-error-stream)
 3577     (clear-stream $_test-error-buffered-file->buffer)
 3578     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3579     68/push 0/imm32
 3580     68/push 0/imm32
 3581     89/<- %edx 4/r32/esp
 3582     (tailor-exit-descriptor %edx 0x10)
 3583     #
 3584     (write _test-input-stream "fn f {\n")
 3585     (write _test-input-stream "  var x/eax: int <- g\n")
 3586     (write _test-input-stream "}\n")
 3587     (write _test-input-stream "fn g {\n")
 3588     (write _test-input-stream "}\n")
 3589     # convert
 3590     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3591     # registers except esp clobbered at this point
 3592     # restore ed
 3593     89/<- %edx 4/r32/esp
 3594     (flush _test-output-buffered-file)
 3595     (flush _test-error-buffered-file)
 3596 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3602     # check output
 3603     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-many-outputs: output should be empty")
 3604     (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")
 3605     # check that stop(1) was called
 3606     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-many-outputs: exit status")
 3607     # don't restore from ebp
 3608     81 0/subop/add %esp 8/imm32
 3609     5d/pop-to-ebp
 3610     c3/return
 3611 
 3612 test-convert-function-call-with-missing-output-register:
 3613     # . prologue
 3614     55/push-ebp
 3615     89/<- %ebp 4/r32/esp
 3616     # setup
 3617     (clear-stream _test-input-stream)
 3618     (clear-stream $_test-input-buffered-file->buffer)
 3619     (clear-stream _test-output-stream)
 3620     (clear-stream $_test-output-buffered-file->buffer)
 3621     (clear-stream _test-error-stream)
 3622     (clear-stream $_test-error-buffered-file->buffer)
 3623     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3624     68/push 0/imm32
 3625     68/push 0/imm32
 3626     89/<- %edx 4/r32/esp
 3627     (tailor-exit-descriptor %edx 0x10)
 3628     #
 3629     (write _test-input-stream "fn f {\n")
 3630     (write _test-input-stream "  var x: int\n")
 3631     (write _test-input-stream "  x <- g\n")
 3632     (write _test-input-stream "}\n")
 3633     (write _test-input-stream "fn g -> _/eax: int {\n")
 3634     (write _test-input-stream "}\n")
 3635     # convert
 3636     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3637     # registers except esp clobbered at this point
 3638     # restore ed
 3639     89/<- %edx 4/r32/esp
 3640     (flush _test-output-buffered-file)
 3641     (flush _test-error-buffered-file)
 3642 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3648     # check output
 3649     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-missing-output-register: output should be empty")
 3650     (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")
 3651     # check that stop(1) was called
 3652     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-missing-output-register: exit status")
 3653     # don't restore from ebp
 3654     81 0/subop/add %esp 8/imm32
 3655     5d/pop-to-ebp
 3656     c3/return
 3657 
 3658 test-convert-function-call-with-incorrect-output-register:
 3659     # . prologue
 3660     55/push-ebp
 3661     89/<- %ebp 4/r32/esp
 3662     # setup
 3663     (clear-stream _test-input-stream)
 3664     (clear-stream $_test-input-buffered-file->buffer)
 3665     (clear-stream _test-output-stream)
 3666     (clear-stream $_test-output-buffered-file->buffer)
 3667     (clear-stream _test-error-stream)
 3668     (clear-stream $_test-error-buffered-file->buffer)
 3669     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3670     68/push 0/imm32
 3671     68/push 0/imm32
 3672     89/<- %edx 4/r32/esp
 3673     (tailor-exit-descriptor %edx 0x10)
 3674     #
 3675     (write _test-input-stream "fn f {\n")
 3676     (write _test-input-stream "  var x/ecx: int <- g\n")
 3677     (write _test-input-stream "}\n")
 3678     (write _test-input-stream "fn g -> _/eax: int {\n")
 3679     (write _test-input-stream "}\n")
 3680     # convert
 3681     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3682     # registers except esp clobbered at this point
 3683     # restore ed
 3684     89/<- %edx 4/r32/esp
 3685     (flush _test-output-buffered-file)
 3686     (flush _test-error-buffered-file)
 3687 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3693     # check output
 3694     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-incorrect-output-register: output should be empty")
 3695     (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")
 3696     # check that stop(1) was called
 3697     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-incorrect-output-register: exit status")
 3698     # don't restore from ebp
 3699     81 0/subop/add %esp 8/imm32
 3700     5d/pop-to-ebp
 3701     c3/return
 3702 
 3703 test-convert-function-with-local-var-dereferenced:
 3704     # . prologue
 3705     55/push-ebp
 3706     89/<- %ebp 4/r32/esp
 3707     # setup
 3708     (clear-stream _test-input-stream)
 3709     (clear-stream $_test-input-buffered-file->buffer)
 3710     (clear-stream _test-output-stream)
 3711     (clear-stream $_test-output-buffered-file->buffer)
 3712     #
 3713     (write _test-input-stream "fn foo {\n")
 3714     (write _test-input-stream "  var x/ecx: (addr int) <- copy 0\n")
 3715     (write _test-input-stream "  increment *x\n")
 3716     (write _test-input-stream "}\n")
 3717     # convert
 3718     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3719     (flush _test-output-buffered-file)
 3720 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 3726     # check output
 3727     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-dereferenced/0")
 3728     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-dereferenced/1")
 3729     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-dereferenced/2")
 3730     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-dereferenced/3")
 3731     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-dereferenced/4")
 3732     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-dereferenced/5")
 3733     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-local-var-dereferenced/6")
 3734     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-function-with-local-var-dereferenced/7")
 3735     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *ecx"  "F - test-convert-function-with-local-var-dereferenced/8")
 3736     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-local-var-dereferenced/9")
 3737     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-dereferenced/10")
 3738     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-dereferenced/11")
 3739     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-dereferenced/12")
 3740     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-dereferenced/13")
 3741     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-dereferenced/14")
 3742     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-dereferenced/15")
 3743     # . epilogue
 3744     89/<- %esp 5/r32/ebp
 3745     5d/pop-to-ebp
 3746     c3/return
 3747 
 3748 test-dereference-of-var-on-stack:
 3749     # . prologue
 3750     55/push-ebp
 3751     89/<- %ebp 4/r32/esp
 3752     # setup
 3753     (clear-stream _test-input-stream)
 3754     (clear-stream $_test-input-buffered-file->buffer)
 3755     (clear-stream _test-output-stream)
 3756     (clear-stream $_test-output-buffered-file->buffer)
 3757     (clear-stream _test-error-stream)
 3758     (clear-stream $_test-error-buffered-file->buffer)
 3759     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3760     68/push 0/imm32
 3761     68/push 0/imm32
 3762     89/<- %edx 4/r32/esp
 3763     (tailor-exit-descriptor %edx 0x10)
 3764     #
 3765     (write _test-input-stream "fn foo {\n")
 3766     (write _test-input-stream "  var x: (addr int)\n")
 3767     (write _test-input-stream "  increment *x\n")
 3768     (write _test-input-stream "}\n")
 3769     # convert
 3770     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3771     # registers except esp clobbered at this point
 3772     # restore ed
 3773     89/<- %edx 4/r32/esp
 3774     (flush _test-output-buffered-file)
 3775     (flush _test-error-buffered-file)
 3776 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3782     # check output
 3783     (check-stream-equal _test-output-stream  ""  "F - test-dereference-of-var-on-stack: output should be empty")
 3784     (check-next-stream-line-equal _test-error-stream  "fn foo: cannot dereference var 'x' on stack"  "F - test-dereference-of-var-on-stack: error message")
 3785     # check that stop(1) was called
 3786     (check-ints-equal *(edx+4) 2 "F - test-dereference-of-var-on-stack: exit status")
 3787     # don't restore from ebp
 3788     81 0/subop/add %esp 8/imm32
 3789     # . epilogue
 3790     5d/pop-to-ebp
 3791     c3/return
 3792 
 3793 test-convert-function-with-byte-operations:
 3794     # . prologue
 3795     55/push-ebp
 3796     89/<- %ebp 4/r32/esp
 3797     # setup
 3798     (clear-stream _test-input-stream)
 3799     (clear-stream $_test-input-buffered-file->buffer)
 3800     (clear-stream _test-output-stream)
 3801     (clear-stream $_test-output-buffered-file->buffer)
 3802     #
 3803     (write _test-input-stream "fn foo {\n")
 3804     (write _test-input-stream "  var x/eax: byte <- copy 0\n")
 3805     (write _test-input-stream "  var y/ecx: byte <- copy 0\n")
 3806     (write _test-input-stream "  y <- copy-byte x\n")
 3807     (write _test-input-stream "  var z/edx: (addr byte) <- copy 0\n")
 3808     (write _test-input-stream "  y <- copy-byte *z\n")
 3809     (write _test-input-stream "  copy-byte-to *z, x\n")
 3810     (write _test-input-stream "}\n")
 3811     # convert
 3812     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3813     (flush _test-output-buffered-file)
 3814 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 3820     # check output
 3821     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-function-with-byte-operations/0")
 3822     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-function-with-byte-operations/1")
 3823     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-function-with-byte-operations/2")
 3824     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-function-with-byte-operations/3")
 3825     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-function-with-byte-operations/4")
 3826     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-function-with-byte-operations/5")
 3827     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-function-with-byte-operations/6")
 3828     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-function-with-byte-operations/7")
 3829     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-function-with-byte-operations/8")
 3830     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"                  "F - test-convert-function-with-byte-operations/9")
 3831     (check-next-stream-line-equal _test-output-stream "    8a/byte-> %eax 0x00000001/r32"           "F - test-convert-function-with-byte-operations/10")
 3832     (check-next-stream-line-equal _test-output-stream "    81 4/subop/and %ecx 0xff/imm32"          "F - test-convert-function-with-byte-operations/11")
 3833     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %edx"                    "F - test-convert-function-with-byte-operations/12")
 3834     (check-next-stream-line-equal _test-output-stream "    ba/copy-to-edx 0/imm32"                  "F - test-convert-function-with-byte-operations/13")
 3835     (check-next-stream-line-equal _test-output-stream "    8a/byte-> *edx 0x00000001/r32"           "F - test-convert-function-with-byte-operations/14")
 3836     (check-next-stream-line-equal _test-output-stream "    81 4/subop/and %ecx 0xff/imm32"          "F - test-convert-function-with-byte-operations/15")
 3837     (check-next-stream-line-equal _test-output-stream "    88/byte<- *edx 0x00000000/r32"           "F - test-convert-function-with-byte-operations/16")
 3838     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %edx"                     "F - test-convert-function-with-byte-operations/17")
 3839     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-function-with-byte-operations/18")
 3840     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-function-with-byte-operations/19")
 3841     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-function-with-byte-operations/20")
 3842     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-function-with-byte-operations/21")
 3843     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-function-with-byte-operations/22")
 3844     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-function-with-byte-operations/23")
 3845     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-function-with-byte-operations/24")
 3846     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-function-with-byte-operations/25")
 3847     # . epilogue
 3848     89/<- %esp 5/r32/ebp
 3849     5d/pop-to-ebp
 3850     c3/return
 3851 
 3852 # variables of type 'byte' are not allowed on the stack
 3853 test-byte-values-on-stack:
 3854     # . prologue
 3855     55/push-ebp
 3856     89/<- %ebp 4/r32/esp
 3857     # setup
 3858     (clear-stream _test-input-stream)
 3859     (clear-stream $_test-input-buffered-file->buffer)
 3860     (clear-stream _test-output-stream)
 3861     (clear-stream $_test-output-buffered-file->buffer)
 3862     (clear-stream _test-error-stream)
 3863     (clear-stream $_test-error-buffered-file->buffer)
 3864     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3865     68/push 0/imm32
 3866     68/push 0/imm32
 3867     89/<- %edx 4/r32/esp
 3868     (tailor-exit-descriptor %edx 0x10)
 3869     #
 3870     (write _test-input-stream "fn foo {\n")
 3871     (write _test-input-stream "  var x: byte\n")
 3872     (write _test-input-stream "}\n")
 3873     # convert
 3874     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3875     # registers except esp clobbered at this point
 3876     # restore ed
 3877     89/<- %edx 4/r32/esp
 3878     (flush _test-output-buffered-file)
 3879     (flush _test-error-buffered-file)
 3880 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3886     # check output
 3887     (check-stream-equal _test-output-stream  ""  "F - test-byte-values-on-stack: output should be empty")
 3888     (check-next-stream-line-equal _test-error-stream  "fn foo: var 'x' of type 'byte' cannot be on the stack"  "F - test-byte-values-on-stack: error message")
 3889     # check that stop(1) was called
 3890     (check-ints-equal *(edx+4) 2 "F - test-byte-values-on-stack: exit status")
 3891     # don't restore from ebp
 3892     81 0/subop/add %esp 8/imm32
 3893     # . epilogue
 3894     5d/pop-to-ebp
 3895     c3/return
 3896 
 3897 # variables of type 'byte' are not allowed in esi or edi
 3898 test-byte-values-in-unsupported-registers:
 3899     # . prologue
 3900     55/push-ebp
 3901     89/<- %ebp 4/r32/esp
 3902     # setup
 3903     (clear-stream _test-input-stream)
 3904     (clear-stream $_test-input-buffered-file->buffer)
 3905     (clear-stream _test-output-stream)
 3906     (clear-stream $_test-output-buffered-file->buffer)
 3907     (clear-stream _test-error-stream)
 3908     (clear-stream $_test-error-buffered-file->buffer)
 3909     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3910     68/push 0/imm32
 3911     68/push 0/imm32
 3912     89/<- %edx 4/r32/esp
 3913     (tailor-exit-descriptor %edx 0x10)
 3914     #
 3915     (write _test-input-stream "fn foo {\n")
 3916     (write _test-input-stream "  var x/esi: byte <- copy 0\n")
 3917     (write _test-input-stream "}\n")
 3918     # convert
 3919     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3920     # registers except esp clobbered at this point
 3921     # restore ed
 3922     89/<- %edx 4/r32/esp
 3923     (flush _test-output-buffered-file)
 3924     (flush _test-error-buffered-file)
 3925 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3931     # check output
 3932     (check-stream-equal _test-output-stream  ""  "F - test-byte-values-in-unsupported-registers: output should be empty")
 3933     (check-next-stream-line-equal _test-error-stream  "fn foo: var 'x' of type 'byte' cannot be in esi or edi"  "F - test-byte-values-in-unsupported-registers: error message")
 3934     # check that stop(1) was called
 3935     (check-ints-equal *(edx+4) 2 "F - test-byte-values-in-unsupported-registers: exit status")
 3936     # don't restore from ebp
 3937     81 0/subop/add %esp 8/imm32
 3938     # . epilogue
 3939     5d/pop-to-ebp
 3940     c3/return
 3941 
 3942 # variables of type 'byte' _can_ be function args. They then occupy 4 bytes.
 3943 test-copy-byte-var-from-fn-arg:
 3944     # . prologue
 3945     55/push-ebp
 3946     89/<- %ebp 4/r32/esp
 3947     # setup
 3948     (clear-stream _test-input-stream)
 3949     (clear-stream $_test-input-buffered-file->buffer)
 3950     (clear-stream _test-output-stream)
 3951     (clear-stream $_test-output-buffered-file->buffer)
 3952     #
 3953     (write _test-input-stream "fn foo x: byte, y: int {\n")
 3954     (write _test-input-stream "  var a/eax: byte <- copy x\n")
 3955     (write _test-input-stream "  var b/eax: int <- copy y\n")
 3956     (write _test-input-stream "}\n")
 3957     # convert
 3958     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3959     (flush _test-output-buffered-file)
 3960 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 3966     # check output
 3967     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-copy-byte-from-fn-arg/0")
 3968     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-copy-byte-from-fn-arg/1")
 3969     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-copy-byte-from-fn-arg/2")
 3970     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-copy-byte-from-fn-arg/3")
 3971     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-copy-byte-from-fn-arg/4")
 3972     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-copy-byte-from-fn-arg/5")
 3973     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-copy-byte-from-fn-arg/6")
 3974     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-copy-byte-from-fn-arg/7")
 3975     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x0000000c) 0x00000000/r32"  "F - test-copy-byte-from-fn-arg/8")
 3976     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"   "F - test-copy-byte-from-fn-arg/9")
 3977     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-copy-byte-from-fn-arg/10")
 3978     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-copy-byte-from-fn-arg/11")
 3979     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-copy-byte-from-fn-arg/12")
 3980     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-copy-byte-from-fn-arg/13")
 3981     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-copy-byte-from-fn-arg/14")
 3982     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-copy-byte-from-fn-arg/15")
 3983     # . epilogue
 3984     89/<- %esp 5/r32/ebp
 3985     5d/pop-to-ebp
 3986     c3/return
 3987 
 3988 test-convert-compare-register-with-literal:
 3989     # . prologue
 3990     55/push-ebp
 3991     89/<- %ebp 4/r32/esp
 3992     # setup
 3993     (clear-stream _test-input-stream)
 3994     (clear-stream $_test-input-buffered-file->buffer)
 3995     (clear-stream _test-output-stream)
 3996     (clear-stream $_test-output-buffered-file->buffer)
 3997     #
 3998     (write _test-input-stream "fn foo {\n")
 3999     (write _test-input-stream "  var x/ecx: int <- copy 0\n")
 4000     (write _test-input-stream "  compare x, 0\n")
 4001     (write _test-input-stream "}\n")
 4002     # convert
 4003     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4004     (flush _test-output-buffered-file)
 4005 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4011     # check output
 4012     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-compare-register-with-literal/0")
 4013     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-compare-register-with-literal/1")
 4014     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-compare-register-with-literal/2")
 4015     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-compare-register-with-literal/3")
 4016     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-compare-register-with-literal/4")
 4017     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-compare-register-with-literal/5")
 4018     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-compare-register-with-literal/6")
 4019     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-compare-register-with-literal/7")
 4020     (check-next-stream-line-equal _test-output-stream "    81 7/subop/compare %ecx 0/imm32"  "F - test-convert-compare-register-with-literal/8")
 4021     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-compare-register-with-literal/9")
 4022     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-compare-register-with-literal/10")
 4023     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-compare-register-with-literal/11")
 4024     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-compare-register-with-literal/12")
 4025     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-compare-register-with-literal/13")
 4026     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-compare-register-with-literal/14")
 4027     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-compare-register-with-literal/15")
 4028     # . epilogue
 4029     89/<- %esp 5/r32/ebp
 4030     5d/pop-to-ebp
 4031     c3/return
 4032 
 4033 test-convert-compare-byte-with-literal:
 4034     # . prologue
 4035     55/push-ebp
 4036     89/<- %ebp 4/r32/esp
 4037     # setup
 4038     (clear-stream _test-input-stream)
 4039     (clear-stream $_test-input-buffered-file->buffer)
 4040     (clear-stream _test-output-stream)
 4041     (clear-stream $_test-output-buffered-file->buffer)
 4042     #
 4043     (write _test-input-stream "fn foo {\n")
 4044     (write _test-input-stream "  var x/ecx: byte <- copy 0\n")
 4045     (write _test-input-stream "  compare x, 0\n")
 4046     (write _test-input-stream "}\n")
 4047     # convert
 4048     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4049     (flush _test-output-buffered-file)
 4050 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4056     # no errors; output is identical to test-convert-compare-register-with-literal
 4057     # . epilogue
 4058     89/<- %esp 5/r32/ebp
 4059     5d/pop-to-ebp
 4060     c3/return
 4061 
 4062 test-unknown-variable:
 4063     # . prologue
 4064     55/push-ebp
 4065     89/<- %ebp 4/r32/esp
 4066     # setup
 4067     (clear-stream _test-input-stream)
 4068     (clear-stream $_test-input-buffered-file->buffer)
 4069     (clear-stream _test-output-stream)
 4070     (clear-stream $_test-output-buffered-file->buffer)
 4071     (clear-stream _test-error-stream)
 4072     (clear-stream $_test-error-buffered-file->buffer)
 4073     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 4074     68/push 0/imm32
 4075     68/push 0/imm32
 4076     89/<- %edx 4/r32/esp
 4077     (tailor-exit-descriptor %edx 0x10)
 4078     #
 4079     (write _test-input-stream "fn foo {\n")
 4080     (write _test-input-stream "  compare x, 0\n")
 4081     (write _test-input-stream "}\n")
 4082     # convert
 4083     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 4084     # registers except esp clobbered at this point
 4085     # restore ed
 4086     89/<- %edx 4/r32/esp
 4087     (flush _test-output-buffered-file)
 4088     (flush _test-error-buffered-file)
 4089 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 4095     # check output
 4096     (check-stream-equal _test-output-stream  ""  "F - test-unknown-variable: output should be empty")
 4097     (check-next-stream-line-equal _test-error-stream  "fn foo: unknown variable 'x'"  "F - test-unknown-variable: error message")
 4098     # check that stop(1) was called
 4099     (check-ints-equal *(edx+4) 2 "F - test-unknown-variable: exit status")
 4100     # don't restore from ebp
 4101     81 0/subop/add %esp 8/imm32
 4102     # . epilogue
 4103     5d/pop-to-ebp
 4104     c3/return
 4105 
 4106 test-convert-function-with-local-var-in-block:
 4107     # . prologue
 4108     55/push-ebp
 4109     89/<- %ebp 4/r32/esp
 4110     # setup
 4111     (clear-stream _test-input-stream)
 4112     (clear-stream $_test-input-buffered-file->buffer)
 4113     (clear-stream _test-output-stream)
 4114     (clear-stream $_test-output-buffered-file->buffer)
 4115     #
 4116     (write _test-input-stream "fn foo {\n")
 4117     (write _test-input-stream "  {\n")
 4118     (write _test-input-stream "    var x: int\n")
 4119     (write _test-input-stream "    increment x\n")
 4120     (write _test-input-stream "  }\n")
 4121     (write _test-input-stream "}\n")
 4122     # convert
 4123     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4124     (flush _test-output-buffered-file)
 4125 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4131     # check output
 4132     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-block/0")
 4133     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-block/1")
 4134     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-block/2")
 4135     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-block/3")
 4136     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-block/4")
 4137     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-block/5")
 4138     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-local-var-in-block/6")
 4139     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-local-var-in-block/7")
 4140     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-local-var-in-block/8")
 4141     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-local-var-in-block/9")
 4142     (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")
 4143     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-local-var-in-block/11")
 4144     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-local-var-in-block/12")
 4145     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-block/13")
 4146     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-block/14")
 4147     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-block/15")
 4148     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-block/16")
 4149     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-block/17")
 4150     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-block/18")
 4151     # . epilogue
 4152     89/<- %esp 5/r32/ebp
 4153     5d/pop-to-ebp
 4154     c3/return
 4155 
 4156 test-convert-function-with-local-var-in-mem-after-block:
 4157     # . prologue
 4158     55/push-ebp
 4159     89/<- %ebp 4/r32/esp
 4160     # setup
 4161     (clear-stream _test-input-stream)
 4162     (clear-stream $_test-input-buffered-file->buffer)
 4163     (clear-stream _test-output-stream)
 4164     (clear-stream $_test-output-buffered-file->buffer)
 4165     #
 4166     (write _test-input-stream "fn foo {\n")
 4167     (write _test-input-stream "  {\n")
 4168     (write _test-input-stream "    var y: int\n")
 4169     (write _test-input-stream "  }\n")
 4170     (write _test-input-stream "  var x: int\n")
 4171     (write _test-input-stream "  increment x\n")
 4172     (write _test-input-stream "}\n")
 4173     # convert
 4174     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4175     (flush _test-output-buffered-file)
 4176 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4182     # check output
 4183     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-mem-after-block/0")
 4184     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-mem-after-block/1")
 4185     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-mem-after-block/2")
 4186     (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")
 4187     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-mem-after-block/4")
 4188     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-mem-after-block/5")
 4189     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-local-var-in-mem-after-block/6")
 4190     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-local-var-in-mem-after-block/7")
 4191     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-local-var-in-mem-after-block/8")
 4192     (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")
 4193     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-local-var-in-mem-after-block/10")
 4194     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-local-var-in-mem-after-block/11")
 4195     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-in-mem-after-block/12")
 4196     (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")
 4197     (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")
 4198     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-mem-after-block/15")
 4199     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-mem-after-block/16")
 4200     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-mem-after-block/17")
 4201     (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")
 4202     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-mem-after-block/19")
 4203     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-mem-after-block/20")
 4204     # . epilogue
 4205     89/<- %esp 5/r32/ebp
 4206     5d/pop-to-ebp
 4207     c3/return
 4208 
 4209 test-convert-function-with-local-var-in-named-block:
 4210     # . prologue
 4211     55/push-ebp
 4212     89/<- %ebp 4/r32/esp
 4213     # setup
 4214     (clear-stream _test-input-stream)
 4215     (clear-stream $_test-input-buffered-file->buffer)
 4216     (clear-stream _test-output-stream)
 4217     (clear-stream $_test-output-buffered-file->buffer)
 4218     #
 4219     (write _test-input-stream "fn foo {\n")
 4220     (write _test-input-stream "  $bar: {\n")
 4221     (write _test-input-stream "    var x: int\n")
 4222     (write _test-input-stream "    increment x\n")
 4223     (write _test-input-stream "  }\n")
 4224     (write _test-input-stream "}\n")
 4225     # convert
 4226     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4227     (flush _test-output-buffered-file)
 4228 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4234     # check output
 4235     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-named-block/0")
 4236     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-named-block/1")
 4237     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-named-block/2")
 4238     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-named-block/3")
 4239     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-named-block/4")
 4240     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-named-block/5")
 4241     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-local-var-in-named-block/6")
 4242     (check-next-stream-line-equal _test-output-stream "$bar:loop:"              "F - test-convert-function-with-local-var-in-named-block/7")
 4243     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-local-var-in-named-block/8")
 4244     (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")
 4245     (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")
 4246     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-local-var-in-named-block/11")
 4247     (check-next-stream-line-equal _test-output-stream "$bar:break:"             "F - test-convert-function-with-local-var-in-named-block/12")
 4248     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-named-block/13")
 4249     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-named-block/14")
 4250     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-named-block/15")
 4251     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-named-block/16")
 4252     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-named-block/17")
 4253     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-named-block/18")
 4254     # . epilogue
 4255     89/<- %esp 5/r32/ebp
 4256     5d/pop-to-ebp
 4257     c3/return
 4258 
 4259 test-unknown-variable-in-named-block:
 4260     # . prologue
 4261     55/push-ebp
 4262     89/<- %ebp 4/r32/esp
 4263     # setup
 4264     (clear-stream _test-input-stream)
 4265     (clear-stream $_test-input-buffered-file->buffer)
 4266     (clear-stream _test-output-stream)
 4267     (clear-stream $_test-output-buffered-file->buffer)
 4268     (clear-stream _test-error-stream)
 4269     (clear-stream $_test-error-buffered-file->buffer)
 4270     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 4271     68/push 0/imm32
 4272     68/push 0/imm32
 4273     89/<- %edx 4/r32/esp
 4274     (tailor-exit-descriptor %edx 0x10)
 4275     #
 4276     (write _test-input-stream "fn foo {\n")
 4277     (write _test-input-stream "  $a: {\n")
 4278     (write _test-input-stream "    compare x, 0\n")
 4279     (write _test-input-stream "  }\n")
 4280     (write _test-input-stream "}\n")
 4281     # convert
 4282     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 4283     # registers except esp clobbered at this point
 4284     # restore ed
 4285     89/<- %edx 4/r32/esp
 4286     (flush _test-output-buffered-file)
 4287     (flush _test-error-buffered-file)
 4288 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 4294     # check output
 4295     (check-stream-equal _test-output-stream  ""  "F - test-unknown-variable-in-named-block: output should be empty")
 4296     (check-next-stream-line-equal _test-error-stream  "fn foo: unknown variable 'x'"  "F - test-unknown-variable-in-named-block: error message")
 4297     # check that stop(1) was called
 4298     (check-ints-equal *(edx+4) 2 "F - test-unknown-variable-in-named-block: exit status")
 4299     # don't restore from ebp
 4300     81 0/subop/add %esp 8/imm32
 4301     # . epilogue
 4302     5d/pop-to-ebp
 4303     c3/return
 4304 
 4305 test-always-shadow-outermost-reg-vars-in-function:
 4306     # . prologue
 4307     55/push-ebp
 4308     89/<- %ebp 4/r32/esp
 4309     # setup
 4310     (clear-stream _test-input-stream)
 4311     (clear-stream $_test-input-buffered-file->buffer)
 4312     (clear-stream _test-output-stream)
 4313     (clear-stream $_test-output-buffered-file->buffer)
 4314     #
 4315     (write _test-input-stream "fn foo {\n")
 4316     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 4317     (write _test-input-stream "}\n")
 4318     # convert
 4319     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4320     (flush _test-output-buffered-file)
 4321 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4327     # check output
 4328     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-always-shadow-outermost-reg-vars-in-function/0")
 4329     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-always-shadow-outermost-reg-vars-in-function/1")
 4330     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-always-shadow-outermost-reg-vars-in-function/2")
 4331     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-always-shadow-outermost-reg-vars-in-function/3")
 4332     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-always-shadow-outermost-reg-vars-in-function/4")
 4333     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-always-shadow-outermost-reg-vars-in-function/5")
 4334     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-compare-register-with-literal/6")
 4335     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-always-shadow-outermost-reg-vars-in-function/8")
 4336     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-compare-register-with-literal/9")
 4337     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-always-shadow-outermost-reg-vars-in-function/12")
 4338     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-always-shadow-outermost-reg-vars-in-function/13")
 4339     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-always-shadow-outermost-reg-vars-in-function/14")
 4340     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-always-shadow-outermost-reg-vars-in-function/15")
 4341     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-always-shadow-outermost-reg-vars-in-function/16")
 4342     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-always-shadow-outermost-reg-vars-in-function/17")
 4343     # . epilogue
 4344     89/<- %esp 5/r32/ebp
 4345     5d/pop-to-ebp
 4346     c3/return
 4347 
 4348 test-shadow-local:
 4349     # . prologue
 4350     55/push-ebp
 4351     89/<- %ebp 4/r32/esp
 4352     # setup
 4353     (clear-stream _test-input-stream)
 4354     (clear-stream $_test-input-buffered-file->buffer)
 4355     (clear-stream _test-output-stream)
 4356     (clear-stream $_test-output-buffered-file->buffer)
 4357     #
 4358     (write _test-input-stream "fn foo {\n")
 4359     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 4360     (write _test-input-stream "  {\n")
 4361     (write _test-input-stream "    var y/ecx: int <- copy 4\n")
 4362     (write _test-input-stream "  }\n")
 4363     (write _test-input-stream "  x <- increment\n")
 4364     (write _test-input-stream "}\n")
 4365     # convert
 4366     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4367     (flush _test-output-buffered-file)
 4368 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4374     # check output
 4375     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-shadow-local/0")
 4376     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-shadow-local/1")
 4377     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-shadow-local/2")
 4378     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-shadow-local/3")
 4379     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-shadow-local/4")
 4380     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-shadow-local/5")
 4381     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-shadow-local/6")
 4382     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-shadow-local/7")
 4383     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-shadow-local/8")
 4384     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-shadow-local/9")
 4385     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %ecx"  "F - test-shadow-local/10")
 4386     (check-next-stream-line-equal _test-output-stream "      b9/copy-to-ecx 4/imm32"  "F - test-shadow-local/11")
 4387     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %ecx" "F - test-shadow-local/12")
 4388     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-shadow-local/13")
 4389     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-shadow-local/14")
 4390     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-shadow-local/15")
 4391     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-shadow-local/16")
 4392     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-shadow-local/17")
 4393     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-shadow-local/18")
 4394     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-shadow-local/19")
 4395     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-shadow-local/20")
 4396     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-shadow-local/21")
 4397     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-shadow-local/22")
 4398     # . epilogue
 4399     89/<- %esp 5/r32/ebp
 4400     5d/pop-to-ebp
 4401     c3/return
 4402 
 4403 test-shadow-name:
 4404     # . prologue
 4405     55/push-ebp
 4406     89/<- %ebp 4/r32/esp
 4407     # setup
 4408     (clear-stream _test-input-stream)
 4409     (clear-stream $_test-input-buffered-file->buffer)
 4410     (clear-stream _test-output-stream)
 4411     (clear-stream $_test-output-buffered-file->buffer)
 4412     #
 4413     (write _test-input-stream "fn foo {\n")
 4414     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 4415     (write _test-input-stream "  {\n")
 4416     (write _test-input-stream "    var x/edx: int <- copy 4\n")
 4417     (write _test-input-stream "  }\n")
 4418     (write _test-input-stream "  x <- increment\n")
 4419     (write _test-input-stream "}\n")
 4420     # convert
 4421     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4422     (flush _test-output-buffered-file)
 4423 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4429     # check output
 4430     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-shadow-name/0")
 4431     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-shadow-name/1")
 4432     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-shadow-name/2")
 4433     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-shadow-name/3")
 4434     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-shadow-name/4")
 4435     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-shadow-name/5")
 4436     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-shadow-name/6")
 4437     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-shadow-name/7")
 4438     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-shadow-name/8")
 4439     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-shadow-name/9")
 4440     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %edx"  "F - test-shadow-name/10")
 4441     (check-next-stream-line-equal _test-output-stream "      ba/copy-to-edx 4/imm32"  "F - test-shadow-name/11")
 4442     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %edx" "F - test-shadow-name/12")
 4443     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-shadow-name/13")
 4444     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-shadow-name/14")
 4445     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-shadow-name/15")
 4446     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-shadow-name/16")
 4447     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-shadow-name/17")
 4448     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-shadow-name/18")
 4449     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-shadow-name/19")
 4450     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-shadow-name/20")
 4451     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-shadow-name/21")
 4452     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-shadow-name/22")
 4453     # . epilogue
 4454     89/<- %esp 5/r32/ebp
 4455     5d/pop-to-ebp
 4456     c3/return
 4457 
 4458 test-shadow-name-2:
 4459     # . prologue
 4460     55/push-ebp
 4461     89/<- %ebp 4/r32/esp
 4462     # setup
 4463     (clear-stream _test-input-stream)
 4464     (clear-stream $_test-input-buffered-file->buffer)
 4465     (clear-stream _test-output-stream)
 4466     (clear-stream $_test-output-buffered-file->buffer)
 4467     #
 4468     (write _test-input-stream "fn foo {\n")
 4469     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 4470     (write _test-input-stream "  {\n")
 4471     (write _test-input-stream "    var x/edx: int <- copy 4\n")
 4472     (write _test-input-stream "    var y/ecx: int <- copy 5\n")
 4473     (write _test-input-stream "  }\n")
 4474     (write _test-input-stream "  x <- increment\n")
 4475     (write _test-input-stream "}\n")
 4476     # convert
 4477     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4478     (flush _test-output-buffered-file)
 4479 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4485     # check output
 4486     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-shadow-name-2/0")
 4487     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-shadow-name-2/1")
 4488     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-shadow-name-2/2")
 4489     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-shadow-name-2/3")
 4490     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-shadow-name-2/4")
 4491     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-shadow-name-2/5")
 4492     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-shadow-name-2/6")
 4493     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-shadow-name-2/7")
 4494     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-shadow-name-2/8")
 4495     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-shadow-name-2/9")
 4496     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %edx"  "F - test-shadow-name-2/10")
 4497     (check-next-stream-line-equal _test-output-stream "      ba/copy-to-edx 4/imm32"  "F - test-shadow-name-2/11")
 4498     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %ecx"  "F - test-shadow-name-2/12")
 4499     (check-next-stream-line-equal _test-output-stream "      b9/copy-to-ecx 5/imm32"  "F - test-shadow-name-2/13")
 4500     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %ecx" "F - test-shadow-name-2/14")
 4501     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %edx" "F - test-shadow-name-2/15")
 4502     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-shadow-name-2/16")
 4503     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-shadow-name-2/17")
 4504     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-shadow-name-2/18")
 4505     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-shadow-name-2/19")
 4506     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-shadow-name-2/20")
 4507     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-shadow-name-2/21")
 4508     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-shadow-name-2/22")
 4509     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-shadow-name-2/23")
 4510     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-shadow-name-2/24")
 4511     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-shadow-name-2/25")
 4512     # . epilogue
 4513     89/<- %esp 5/r32/ebp
 4514     5d/pop-to-ebp
 4515     c3/return
 4516 
 4517 test-do-not-spill-same-register-in-block:
 4518     # . prologue
 4519     55/push-ebp
 4520     89/<- %ebp 4/r32/esp
 4521     # setup
 4522     (clear-stream _test-input-stream)
 4523     (clear-stream $_test-input-buffered-file->buffer)
 4524     (clear-stream _test-output-stream)
 4525     (clear-stream $_test-output-buffered-file->buffer)
 4526     #
 4527     (write _test-input-stream "fn foo {\n")
 4528     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 4529     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
 4530     (write _test-input-stream "  y <- increment\n")
 4531     (write _test-input-stream "}\n")
 4532     # convert
 4533     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4534     (flush _test-output-buffered-file)
 4535 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4541     # check output
 4542     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-do-not-spill-same-register-in-block/0")
 4543     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-do-not-spill-same-register-in-block/1")
 4544     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-do-not-spill-same-register-in-block/2")
 4545     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-do-not-spill-same-register-in-block/3")
 4546     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-do-not-spill-same-register-in-block/4")
 4547     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-do-not-spill-same-register-in-block/5")
 4548     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-do-not-spill-same-register-in-block/6")
 4549     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-do-not-spill-same-register-in-block/7")
 4550     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 4/imm32"  "F - test-do-not-spill-same-register-in-block/8")
 4551     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-do-not-spill-same-register-in-block/9")
 4552     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-do-not-spill-same-register-in-block/10")
 4553     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-do-not-spill-same-register-in-block/11")
 4554     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-do-not-spill-same-register-in-block/12")
 4555     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-do-not-spill-same-register-in-block/13")
 4556     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-do-not-spill-same-register-in-block/14")
 4557     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-do-not-spill-same-register-in-block/15")
 4558     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-do-not-spill-same-register-in-block/16")
 4559     # . epilogue
 4560     89/<- %esp 5/r32/ebp
 4561     5d/pop-to-ebp
 4562     c3/return
 4563 
 4564 test-spill-different-register-in-block:
 4565     # . prologue
 4566     55/push-ebp
 4567     89/<- %ebp 4/r32/esp
 4568     # setup
 4569     (clear-stream _test-input-stream)
 4570     (clear-stream $_test-input-buffered-file->buffer)
 4571     (clear-stream _test-output-stream)
 4572     (clear-stream $_test-output-buffered-file->buffer)
 4573     #
 4574     (write _test-input-stream "fn foo {\n")
 4575     (write _test-input-stream "  var x/eax: int <- copy 3\n")
 4576     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
 4577     (write _test-input-stream "  y <- increment\n")
 4578     (write _test-input-stream "}\n")
 4579     # convert
 4580     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4581     (flush _test-output-buffered-file)
 4582 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4588     # check output
 4589     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-spill-different-register-in-block/0")
 4590     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-spill-different-register-in-block/1")
 4591     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-spill-different-register-in-block/2")
 4592     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-spill-different-register-in-block/3")
 4593     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-spill-different-register-in-block/4")
 4594     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-spill-different-register-in-block/5")
 4595     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-spill-different-register-in-block/6")
 4596     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 3/imm32"  "F - test-spill-different-register-in-block/7")
 4597     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-spill-different-register-in-block/8")
 4598     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 4/imm32"  "F - test-spill-different-register-in-block/9")
 4599     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-spill-different-register-in-block/10")
 4600     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-spill-different-register-in-block/11")
 4601     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-spill-different-register-in-block/12")
 4602     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-spill-different-register-in-block/13")
 4603     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-spill-different-register-in-block/14")
 4604     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-spill-different-register-in-block/15")
 4605     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-spill-different-register-in-block/16")
 4606     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-spill-different-register-in-block/17")
 4607     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-spill-different-register-in-block/18")
 4608     # . epilogue
 4609     89/<- %esp 5/r32/ebp
 4610     5d/pop-to-ebp
 4611     c3/return
 4612 
 4613 test-convert-function-with-branches-in-block:
 4614     # . prologue
 4615     55/push-ebp
 4616     89/<- %ebp 4/r32/esp
 4617     # setup
 4618     (clear-stream _test-input-stream)
 4619     (clear-stream $_test-input-buffered-file->buffer)
 4620     (clear-stream _test-output-stream)
 4621     (clear-stream $_test-output-buffered-file->buffer)
 4622     #
 4623     (write _test-input-stream "fn foo x: int {\n")
 4624     (write _test-input-stream "  {\n")
 4625     (write _test-input-stream "    break-if->=\n")
 4626     (write _test-input-stream "    loop-if-addr<\n")
 4627     (write _test-input-stream "    increment x\n")
 4628     (write _test-input-stream "    loop\n")
 4629     (write _test-input-stream "  }\n")
 4630     (write _test-input-stream "}\n")
 4631     # convert
 4632     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4633     (flush _test-output-buffered-file)
 4634 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4640     # check output
 4641     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-in-block/0")
 4642     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-in-block/1")
 4643     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-in-block/2")
 4644     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-in-block/3")
 4645     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-in-block/4")
 4646     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-in-block/5")
 4647     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-in-block/6")
 4648     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-branches-in-block/7")
 4649     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-block/8")
 4650     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-in-block/9")
 4651     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-with-branches-in-block/10")
 4652     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-block/11")
 4653     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-block/12")
 4654     (check-next-stream-line-equal _test-output-stream "        0f 83/jump-if-addr>= break/disp32"  "F - test-convert-function-with-branches-in-block/13")
 4655     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:loop/disp32"  "F - test-convert-function-with-branches-in-block/14")
 4656     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-block/15")
 4657     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0x00000008)"  "F - test-convert-function-with-branches-in-block/16")
 4658     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"  "F - test-convert-function-with-branches-in-block/17")
 4659     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-in-block/18")
 4660     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-branches-in-block/19")
 4661     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-in-block/20")
 4662     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-in-block/21")
 4663     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-in-block/22")
 4664     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-in-block/23")
 4665     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-in-block/24")
 4666     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-in-block/25")
 4667     # . epilogue
 4668     89/<- %esp 5/r32/ebp
 4669     5d/pop-to-ebp
 4670     c3/return
 4671 
 4672 test-convert-function-with-branches-in-block-2:
 4673     # . prologue
 4674     55/push-ebp
 4675     89/<- %ebp 4/r32/esp
 4676     # setup
 4677     (clear-stream _test-input-stream)
 4678     (clear-stream $_test-input-buffered-file->buffer)
 4679     (clear-stream _test-output-stream)
 4680     (clear-stream $_test-output-buffered-file->buffer)
 4681     #
 4682     (write _test-input-stream "fn foo x: int {\n")
 4683     (write _test-input-stream "  {\n")
 4684     (write _test-input-stream "    break-if->=\n")
 4685     (write _test-input-stream "    loop-if-float<\n")
 4686     (write _test-input-stream "    increment x\n")
 4687     (write _test-input-stream "    loop\n")
 4688     (write _test-input-stream "  }\n")
 4689     (write _test-input-stream "}\n")
 4690     # convert
 4691     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4692     (flush _test-output-buffered-file)
 4693 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4699     # check output
 4700     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-in-block/0")
 4701     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-in-block/1")
 4702     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-in-block/2")
 4703     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-in-block/3")
 4704     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-in-block/4")
 4705     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-in-block/5")
 4706     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-in-block/6")
 4707     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-branches-in-block/7")
 4708     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-block/8")
 4709     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-in-block/9")
 4710     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-with-branches-in-block/10")
 4711     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-block/11")
 4712     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-block/12")
 4713     (check-next-stream-line-equal _test-output-stream "        0f 83/jump-if-addr>= break/disp32"  "F - test-convert-function-with-branches-in-block/13")
 4714     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:loop/disp32"  "F - test-convert-function-with-branches-in-block/14")
 4715     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-block/15")
 4716     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0x00000008)"  "F - test-convert-function-with-branches-in-block/16")
 4717     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"  "F - test-convert-function-with-branches-in-block/17")
 4718     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-in-block/18")
 4719     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-branches-in-block/19")
 4720     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-in-block/20")
 4721     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-in-block/21")
 4722     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-in-block/22")
 4723     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-in-block/23")
 4724     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-in-block/24")
 4725     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-in-block/25")
 4726     # . epilogue
 4727     89/<- %esp 5/r32/ebp
 4728     5d/pop-to-ebp
 4729     c3/return
 4730 
 4731 test-convert-function-with-branches-in-named-block:
 4732     # . prologue
 4733     55/push-ebp
 4734     89/<- %ebp 4/r32/esp
 4735     # setup
 4736     (clear-stream _test-input-stream)
 4737     (clear-stream $_test-input-buffered-file->buffer)
 4738     (clear-stream _test-output-stream)
 4739     (clear-stream $_test-output-buffered-file->buffer)
 4740     #
 4741     (write _test-input-stream "fn foo x: int {\n")
 4742     (write _test-input-stream "  $bar: {\n")
 4743     (write _test-input-stream "    break-if->= $bar\n")
 4744     (write _test-input-stream "    loop-if-addr< $bar\n")
 4745     (write _test-input-stream "    increment x\n")
 4746     (write _test-input-stream "    loop\n")
 4747     (write _test-input-stream "  }\n")
 4748     (write _test-input-stream "}\n")
 4749     # convert
 4750     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4751     (flush _test-output-buffered-file)
 4752 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4758     # check output
 4759     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-in-named-block/0")
 4760     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-in-named-block/1")
 4761     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-in-named-block/2")
 4762     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-in-named-block/3")
 4763     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-in-named-block/4")
 4764     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-in-named-block/5")
 4765     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-in-named-block/6")
 4766     (check-next-stream-line-equal _test-output-stream "$bar:loop:"              "F - test-convert-function-with-branches-in-named-block/7")
 4767     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-named-block/8")
 4768     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-in-named-block/9")
 4769     (check-next-stream-line-equal _test-output-stream "        e9/jump $bar:break/disp32"  "F - test-convert-function-with-branches-in-named-block/10")
 4770     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-named-block/11")
 4771     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-named-block/12")
 4772     (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")
 4773     (check-next-stream-line-equal _test-output-stream "        e9/jump $bar:loop/disp32"  "F - test-convert-function-with-branches-in-named-block/14")
 4774     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-named-block/15")
 4775     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0x00000008)"  "F - test-convert-function-with-branches-in-named-block/16")
 4776     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"   "F - test-convert-function-with-branches-in-named-block/17")
 4777     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-in-named-block/18")
 4778     (check-next-stream-line-equal _test-output-stream "$bar:break:"             "F - test-convert-function-with-branches-in-named-block/19")
 4779     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-in-named-block/20")
 4780     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-in-named-block/21")
 4781     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-in-named-block/22")
 4782     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-in-named-block/23")
 4783     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-in-named-block/24")
 4784     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-in-named-block/25")
 4785     # . epilogue
 4786     89/<- %esp 5/r32/ebp
 4787     5d/pop-to-ebp
 4788     c3/return
 4789 
 4790 test-convert-function-with-var-in-nested-block:
 4791     # . prologue
 4792     55/push-ebp
 4793     89/<- %ebp 4/r32/esp
 4794     # setup
 4795     (clear-stream _test-input-stream)
 4796     (clear-stream $_test-input-buffered-file->buffer)
 4797     (clear-stream _test-output-stream)
 4798     (clear-stream $_test-output-buffered-file->buffer)
 4799     #
 4800     (write _test-input-stream "fn foo x: int {\n")
 4801     (write _test-input-stream "  {\n")
 4802     (write _test-input-stream "    {\n")
 4803     (write _test-input-stream "      var x: int\n")
 4804     (write _test-input-stream "      increment x\n")
 4805     (write _test-input-stream "    }\n")
 4806     (write _test-input-stream "  }\n")
 4807     (write _test-input-stream "}\n")
 4808     # convert
 4809     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4810     (flush _test-output-buffered-file)
 4811 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4817     # check output
 4818     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-var-in-nested-block/0")
 4819     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-var-in-nested-block/1")
 4820     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-var-in-nested-block/2")
 4821     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-var-in-nested-block/3")
 4822     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-var-in-nested-block/4")
 4823     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-var-in-nested-block/5")
 4824     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-var-in-nested-block/6")
 4825     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-var-in-nested-block/7")
 4826     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-var-in-nested-block/8")
 4827     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-var-in-nested-block/9")
 4828     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-var-in-nested-block/10")
 4829     (check-next-stream-line-equal _test-output-stream "        ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-var-in-nested-block/11")
 4830     (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")
 4831     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-var-in-nested-block/13")
 4832     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-var-in-nested-block/14")
 4833     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-var-in-nested-block/15")
 4834     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-var-in-nested-block/16")
 4835     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-var-in-nested-block/17")
 4836     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-var-in-nested-block/18")
 4837     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-var-in-nested-block/19")
 4838     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-var-in-nested-block/20")
 4839     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-var-in-nested-block/21")
 4840     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-var-in-nested-block/22")
 4841     # . epilogue
 4842     89/<- %esp 5/r32/ebp
 4843     5d/pop-to-ebp
 4844     c3/return
 4845 
 4846 test-convert-function-with-multiple-vars-in-nested-blocks:
 4847     # . prologue
 4848     55/push-ebp
 4849     89/<- %ebp 4/r32/esp
 4850     # setup
 4851     (clear-stream _test-input-stream)
 4852     (clear-stream $_test-input-buffered-file->buffer)
 4853     (clear-stream _test-output-stream)
 4854     (clear-stream $_test-output-buffered-file->buffer)
 4855     #
 4856     (write _test-input-stream "fn foo x: int {\n")
 4857     (write _test-input-stream "  {\n")
 4858     (write _test-input-stream "    var x/eax: int <- copy 0\n")
 4859     (write _test-input-stream "    {\n")
 4860     (write _test-input-stream "      var y: int\n")
 4861     (write _test-input-stream "      x <- add y\n")
 4862     (write _test-input-stream "    }\n")
 4863     (write _test-input-stream "  }\n")
 4864     (write _test-input-stream "}\n")
 4865     # convert
 4866     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4867     (flush _test-output-buffered-file)
 4868 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4874     # check output
 4875     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-multiple-vars-in-nested-blocks/0")
 4876     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-multiple-vars-in-nested-blocks/1")
 4877     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-multiple-vars-in-nested-blocks/2")
 4878     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/3")
 4879     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-multiple-vars-in-nested-blocks/4")
 4880     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/5")
 4881     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-multiple-vars-in-nested-blocks/6")
 4882     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/7")
 4883     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %eax"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/8")
 4884     (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")
 4885     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-multiple-vars-in-nested-blocks/10")
 4886     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/11")
 4887     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-multiple-vars-in-nested-blocks/12")
 4888     (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")
 4889     (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")
 4890     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-multiple-vars-in-nested-blocks/15")
 4891     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/16")
 4892     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %eax"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/17")
 4893     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-multiple-vars-in-nested-blocks/18")
 4894     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/19")
 4895     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-multiple-vars-in-nested-blocks/20")
 4896     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/21")
 4897     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-multiple-vars-in-nested-blocks/22")
 4898     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/23")
 4899     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-multiple-vars-in-nested-blocks/24")
 4900     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-multiple-vars-in-nested-blocks/25")
 4901     # . epilogue
 4902     89/<- %esp 5/r32/ebp
 4903     5d/pop-to-ebp
 4904     c3/return
 4905 
 4906 test-convert-function-with-branches-and-local-vars:
 4907     # A conditional 'break' after a 'var' in a block is converted into a
 4908     # nested block that performs all necessary cleanup before jumping. This
 4909     # results in some ugly code duplication.
 4910     # . prologue
 4911     55/push-ebp
 4912     89/<- %ebp 4/r32/esp
 4913     # setup
 4914     (clear-stream _test-input-stream)
 4915     (clear-stream $_test-input-buffered-file->buffer)
 4916     (clear-stream _test-output-stream)
 4917     (clear-stream $_test-output-buffered-file->buffer)
 4918     #
 4919     (write _test-input-stream "fn foo {\n")
 4920     (write _test-input-stream "  {\n")
 4921     (write _test-input-stream "    var x: int\n")
 4922     (write _test-input-stream "    break-if->=\n")
 4923     (write _test-input-stream "    increment x\n")
 4924     (write _test-input-stream "  }\n")
 4925     (write _test-input-stream "}\n")
 4926     # convert
 4927     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4928     (flush _test-output-buffered-file)
 4929 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4935     # check output
 4936     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-and-local-vars/0")
 4937     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-and-local-vars/1")
 4938     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-and-local-vars/2")
 4939     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-and-local-vars/3")
 4940     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-and-local-vars/4")
 4941     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-and-local-vars/5")
 4942     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-and-local-vars/6")
 4943     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-branches-and-local-vars/7")
 4944     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-branches-and-local-vars/8")
 4945     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-and-local-vars/9")
 4946     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-and-local-vars/10")
 4947     (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")
 4948     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-with-branches-and-local-vars/12")
 4949     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-and-local-vars/13")
 4950     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-branches-and-local-vars/14")
 4951     (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")
 4952     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-and-local-vars/16")
 4953     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-branches-and-local-vars/17")
 4954     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-and-local-vars/18")
 4955     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-and-local-vars/19")
 4956     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-and-local-vars/20")
 4957     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-and-local-vars/21")
 4958     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-and-local-vars/22")
 4959     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-and-local-vars/23")
 4960     # . epilogue
 4961     89/<- %esp 5/r32/ebp
 4962     5d/pop-to-ebp
 4963     c3/return
 4964 
 4965 test-convert-function-with-conditional-loops-and-local-vars:
 4966     # A conditional 'loop' after a 'var' in a block is converted into a nested
 4967     # block that performs all necessary cleanup before jumping. This results
 4968     # in some ugly code duplication.
 4969     # . prologue
 4970     55/push-ebp
 4971     89/<- %ebp 4/r32/esp
 4972     # setup
 4973     (clear-stream _test-input-stream)
 4974     (clear-stream $_test-input-buffered-file->buffer)
 4975     (clear-stream _test-output-stream)
 4976     (clear-stream $_test-output-buffered-file->buffer)
 4977     #
 4978     (write _test-input-stream "fn foo {\n")
 4979     (write _test-input-stream "  {\n")
 4980     (write _test-input-stream "    var x: int\n")
 4981     (write _test-input-stream "    loop-if->=\n")
 4982     (write _test-input-stream "    increment x\n")
 4983     (write _test-input-stream "  }\n")
 4984     (write _test-input-stream "}\n")
 4985     # convert
 4986     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4987     (flush _test-output-buffered-file)
 4988 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4994     # check output
 4995     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-conditional-loops-and-local-vars/0")
 4996     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-conditional-loops-and-local-vars/1")
 4997     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-conditional-loops-and-local-vars/2")
 4998     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-conditional-loops-and-local-vars/3")
 4999     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-conditional-loops-and-local-vars/4")
 5000     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-conditional-loops-and-local-vars/5")
 5001     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-conditional-loops-and-local-vars/6")
 5002     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-conditional-loops-and-local-vars/7")
 5003     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-conditional-loops-and-local-vars/8")
 5004     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-conditional-loops-and-local-vars/9")
 5005     (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")
 5006     (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")
 5007     (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")
 5008     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-conditional-loops-and-local-vars/13")
 5009     (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")
 5010     (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")
 5011     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-conditional-loops-and-local-vars/16")
 5012     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-conditional-loops-and-local-vars/17")
 5013     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-conditional-loops-and-local-vars/18")
 5014     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-conditional-loops-and-local-vars/19")
 5015     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-conditional-loops-and-local-vars/20")
 5016     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-conditional-loops-and-local-vars/21")
 5017     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-conditional-loops-and-local-vars/22")
 5018     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-conditional-loops-and-local-vars/23")
 5019     # . epilogue
 5020     89/<- %esp 5/r32/ebp
 5021     5d/pop-to-ebp
 5022     c3/return
 5023 
 5024 test-convert-function-with-unconditional-loops-and-local-vars:
 5025     # An unconditional 'loop' after a 'var' in a block is emitted _after_ the
 5026     # regular block cleanup. Any instructions after 'loop' are dead and
 5027     # therefore skipped.
 5028     # . prologue
 5029     55/push-ebp
 5030     89/<- %ebp 4/r32/esp
 5031     # setup
 5032     (clear-stream _test-input-stream)
 5033     (clear-stream $_test-input-buffered-file->buffer)
 5034     (clear-stream _test-output-stream)
 5035     (clear-stream $_test-output-buffered-file->buffer)
 5036     #
 5037     (write _test-input-stream "fn foo {\n")
 5038     (write _test-input-stream "  {\n")
 5039     (write _test-input-stream "    var x: int\n")
 5040     (write _test-input-stream "    loop\n")
 5041     (write _test-input-stream "    increment x\n")
 5042     (write _test-input-stream "  }\n")
 5043     (write _test-input-stream "}\n")
 5044     # convert
 5045     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5046     (flush _test-output-buffered-file)
 5047 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5053     # check output
 5054     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-unconditional-loops-and-local-vars/0")
 5055     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-unconditional-loops-and-local-vars/1")
 5056     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-unconditional-loops-and-local-vars/2")
 5057     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-unconditional-loops-and-local-vars/3")
 5058     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-unconditional-loops-and-local-vars/4")
 5059     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-unconditional-loops-and-local-vars/5")
 5060     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-unconditional-loops-and-local-vars/6")
 5061     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-unconditional-loops-and-local-vars/7")
 5062     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-unconditional-loops-and-local-vars/8")
 5063     (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")
 5064     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"  "F - test-convert-function-with-unconditional-loops-and-local-vars/10")
 5065     # not emitted:                                           ff 0/subop/increment *(ebp+0xfffffffc)
 5066     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-unconditional-loops-and-local-vars/11")
 5067     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-unconditional-loops-and-local-vars/12")
 5068     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-unconditional-loops-and-local-vars/13")
 5069     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-unconditional-loops-and-local-vars/14")
 5070     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-unconditional-loops-and-local-vars/15")
 5071     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-unconditional-loops-and-local-vars/16")
 5072     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-unconditional-loops-and-local-vars/17")
 5073     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-unconditional-loops-and-local-vars/18")
 5074     # . epilogue
 5075     89/<- %esp 5/r32/ebp
 5076     5d/pop-to-ebp
 5077     c3/return
 5078 
 5079 test-convert-function-with-branches-and-loops-and-local-vars:
 5080     # . prologue
 5081     55/push-ebp
 5082     89/<- %ebp 4/r32/esp
 5083     # setup
 5084     (clear-stream _test-input-stream)
 5085     (clear-stream $_test-input-buffered-file->buffer)
 5086     (clear-stream _test-output-stream)
 5087     (clear-stream $_test-output-buffered-file->buffer)
 5088     #
 5089     (write _test-input-stream "fn foo {\n")
 5090     (write _test-input-stream "  {\n")
 5091     (write _test-input-stream "    var x: int\n")
 5092     (write _test-input-stream "    break-if->=\n")
 5093     (write _test-input-stream "    increment x\n")
 5094     (write _test-input-stream "    loop\n")
 5095     (write _test-input-stream "  }\n")
 5096     (write _test-input-stream "}\n")
 5097     # convert
 5098     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5099     (flush _test-output-buffered-file)
 5100 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5106     # check output
 5107     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-and-loops-and-local-vars/0")
 5108     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-and-loops-and-local-vars/1")
 5109     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-and-loops-and-local-vars/2")
 5110     (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")
 5111     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-and-loops-and-local-vars/4")
 5112     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-and-loops-and-local-vars/5")
 5113     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-and-loops-and-local-vars/6")
 5114     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-branches-and-loops-and-local-vars/7")
 5115     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-branches-and-loops-and-local-vars/8")
 5116     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-and-loops-and-local-vars/9")
 5117     (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")
 5118     (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")
 5119     (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")
 5120     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-and-loops-and-local-vars/13")
 5121     (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")
 5122     (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")
 5123     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"  "F - test-convert-function-with-branches-and-loops-and-local-vars/16")
 5124     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-and-loops-and-local-vars/17")
 5125     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-branches-and-loops-and-local-vars/18")
 5126     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-and-loops-and-local-vars/19")
 5127     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-and-loops-and-local-vars/20")
 5128     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-and-loops-and-local-vars/21")
 5129     (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")
 5130     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-and-loops-and-local-vars/23")
 5131     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-and-loops-and-local-vars/24")
 5132     # . epilogue
 5133     89/<- %esp 5/r32/ebp
 5134     5d/pop-to-ebp
 5135     c3/return
 5136 
 5137 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars:
 5138     # . prologue
 5139     55/push-ebp
 5140     89/<- %ebp 4/r32/esp
 5141     # setup
 5142     (clear-stream _test-input-stream)
 5143     (clear-stream $_test-input-buffered-file->buffer)
 5144     (clear-stream _test-output-stream)
 5145     (clear-stream $_test-output-buffered-file->buffer)
 5146     #
 5147     (write _test-input-stream "fn foo {\n")
 5148     (write _test-input-stream "  a: {\n")
 5149     (write _test-input-stream "    var x: int\n")
 5150     (write _test-input-stream "    {\n")
 5151     (write _test-input-stream "      var y: int\n")
 5152     (write _test-input-stream "      break-if->= a\n")
 5153     (write _test-input-stream "      increment x\n")
 5154     (write _test-input-stream "      loop\n")
 5155     (write _test-input-stream "    }\n")
 5156     (write _test-input-stream "  }\n")
 5157     (write _test-input-stream "}\n")
 5158     # convert
 5159     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5160     (flush _test-output-buffered-file)
 5161 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5167     # check output
 5168     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/0")
 5169     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/1")
 5170     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/2")
 5171     (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")
 5172     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/4")
 5173     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/5")
 5174     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/6")
 5175     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/7")
 5176     (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")
 5177     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/9")
 5178     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/10")
 5179     (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")
 5180     (check-next-stream-line-equal _test-output-stream "        {"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/12")
 5181     (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")
 5182     (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")
 5183     (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")
 5184     (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")
 5185     (check-next-stream-line-equal _test-output-stream "        }"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/17")
 5186     (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")
 5187     (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")
 5188     (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")
 5189     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/21")
 5190     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/22")
 5191     (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")
 5192     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/24")
 5193     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/25")
 5194     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/26")
 5195     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/27")
 5196     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/28")
 5197     (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")
 5198     (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")
 5199     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/31")
 5200     # . epilogue
 5201     89/<- %esp 5/r32/ebp
 5202     5d/pop-to-ebp
 5203     c3/return
 5204 
 5205 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2:
 5206     # . prologue
 5207     55/push-ebp
 5208     89/<- %ebp 4/r32/esp
 5209     # setup
 5210     (clear-stream _test-input-stream)
 5211     (clear-stream $_test-input-buffered-file->buffer)
 5212     (clear-stream _test-output-stream)
 5213     (clear-stream $_test-output-buffered-file->buffer)
 5214     # non-local conditional branch from a block without a local variable,
 5215     # unwinding a local on the stack
 5216     (write _test-input-stream "fn foo {\n")
 5217     (write _test-input-stream "  a: {\n")
 5218     (write _test-input-stream "    var x: int\n")
 5219     (write _test-input-stream "    {\n")
 5220     (write _test-input-stream "      break-if->= a\n")
 5221     (write _test-input-stream "    }\n")
 5222     (write _test-input-stream "  }\n")
 5223     (write _test-input-stream "}\n")
 5224     # convert
 5225     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5226     (flush _test-output-buffered-file)
 5227 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5233     # check output
 5234     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/0")
 5235     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/1")
 5236     (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")
 5237     (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")
 5238     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/4")
 5239     (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")
 5240     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/6")
 5241     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/7")
 5242     (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")
 5243     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/9")
 5244     (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")
 5245     (check-next-stream-line-equal _test-output-stream "        {"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/11")
 5246     (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")
 5247     (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")
 5248     (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")
 5249     (check-next-stream-line-equal _test-output-stream "        }"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/15")
 5250     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/16")
 5251     (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")
 5252     (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")
 5253     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/19")
 5254     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/20")
 5255     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/21")
 5256     (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")
 5257     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/23")
 5258     (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")
 5259     (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")
 5260     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/26")
 5261     # . epilogue
 5262     89/<- %esp 5/r32/ebp
 5263     5d/pop-to-ebp
 5264     c3/return
 5265 
 5266 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3:
 5267     # . prologue
 5268     55/push-ebp
 5269     89/<- %ebp 4/r32/esp
 5270     # setup
 5271     (clear-stream _test-input-stream)
 5272     (clear-stream $_test-input-buffered-file->buffer)
 5273     (clear-stream _test-output-stream)
 5274     (clear-stream $_test-output-buffered-file->buffer)
 5275     # non-local unconditional branch from a block without a local variable,
 5276     # unwinding a local on the stack
 5277     (write _test-input-stream "fn foo {\n")
 5278     (write _test-input-stream "  a: {\n")
 5279     (write _test-input-stream "    var x: int\n")
 5280     (write _test-input-stream "    {\n")
 5281     (write _test-input-stream "      break a\n")
 5282     (write _test-input-stream "    }\n")
 5283     (write _test-input-stream "  }\n")
 5284     (write _test-input-stream "}\n")
 5285     # convert
 5286     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5287     (flush _test-output-buffered-file)
 5288 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5294     # check output
 5295     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/0")
 5296     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/1")
 5297     (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")
 5298     (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")
 5299     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/4")
 5300     (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")
 5301     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/6")
 5302     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/7")
 5303     (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")
 5304     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/9")
 5305     (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")
 5306     (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")
 5307     (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")
 5308     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/14")
 5309     (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")
 5310     (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")
 5311     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/17")
 5312     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/18")
 5313     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/19")
 5314     (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")
 5315     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/21")
 5316     (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")
 5317     (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")
 5318     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/24")
 5319     # . epilogue
 5320     89/<- %esp 5/r32/ebp
 5321     5d/pop-to-ebp
 5322     c3/return
 5323 
 5324 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4:
 5325     # . prologue
 5326     55/push-ebp
 5327     89/<- %ebp 4/r32/esp
 5328     # setup
 5329     (clear-stream _test-input-stream)
 5330     (clear-stream $_test-input-buffered-file->buffer)
 5331     (clear-stream _test-output-stream)
 5332     (clear-stream $_test-output-buffered-file->buffer)
 5333     #
 5334     (write _test-input-stream "fn foo {\n")
 5335     (write _test-input-stream "  a: {\n")
 5336     (write _test-input-stream "    var x/esi: int <- copy 0\n")
 5337     (write _test-input-stream "    {\n")
 5338     (write _test-input-stream "      break a\n")
 5339     (write _test-input-stream "    }\n")
 5340     (write _test-input-stream "  }\n")
 5341     (write _test-input-stream "}\n")
 5342     # convert
 5343     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5344     (flush _test-output-buffered-file)
 5345 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5351     # check output
 5352     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/0")
 5353     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/1")
 5354     (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")
 5355     (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")
 5356     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/4")
 5357     (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")
 5358     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/6")
 5359     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/7")
 5360     (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")
 5361     (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")
 5362     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/10")
 5363     (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")
 5364     (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")
 5365     (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")
 5366     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/14")
 5367     (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")
 5368     (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")
 5369     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/17")
 5370     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/18")
 5371     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/19")
 5372     (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")
 5373     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/21")
 5374     (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")
 5375     (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")
 5376     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/24")
 5377     # . epilogue
 5378     89/<- %esp 5/r32/ebp
 5379     5d/pop-to-ebp
 5380     c3/return
 5381 
 5382 test-convert-function-with-nonlocal-unconditional-break-and-local-vars:
 5383     # . prologue
 5384     55/push-ebp
 5385     89/<- %ebp 4/r32/esp
 5386     # setup
 5387     (clear-stream _test-input-stream)
 5388     (clear-stream $_test-input-buffered-file->buffer)
 5389     (clear-stream _test-output-stream)
 5390     (clear-stream $_test-output-buffered-file->buffer)
 5391     #
 5392     (write _test-input-stream "fn foo {\n")
 5393     (write _test-input-stream "  a: {\n")
 5394     (write _test-input-stream "    var x: int\n")
 5395     (write _test-input-stream "    {\n")
 5396     (write _test-input-stream "      var y: int\n")
 5397     (write _test-input-stream "      break a\n")
 5398     (write _test-input-stream "      increment x\n")
 5399     (write _test-input-stream "    }\n")
 5400     (write _test-input-stream "  }\n")
 5401     (write _test-input-stream "}\n")
 5402     # convert
 5403     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5404     (flush _test-output-buffered-file)
 5405 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5411     # check output
 5412     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/0")
 5413     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/1")
 5414     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/2")
 5415     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/3")
 5416     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/4")
 5417     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/5")
 5418     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/6")
 5419     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/7")
 5420     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/8")
 5421     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/9")
 5422     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/10")
 5423     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/11")
 5424     (check-next-stream-line-equal _test-output-stream "        81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/12")
 5425     (check-next-stream-line-equal _test-output-stream "        81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/13")
 5426     (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")
 5427     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/15")
 5428     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/16")
 5429     (check-next-stream-line-equal _test-output-stream "      81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/17")
 5430     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/18")
 5431     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/19")
 5432     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/20")
 5433     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/21")
 5434     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/22")
 5435     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/23")
 5436     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/24")
 5437     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/25")
 5438     # . epilogue
 5439     89/<- %esp 5/r32/ebp
 5440     5d/pop-to-ebp
 5441     c3/return
 5442 
 5443 test-convert-function-with-unconditional-break-and-local-vars:
 5444     # . prologue
 5445     55/push-ebp
 5446     89/<- %ebp 4/r32/esp
 5447     # setup
 5448     (clear-stream _test-input-stream)
 5449     (clear-stream $_test-input-buffered-file->buffer)
 5450     (clear-stream _test-output-stream)
 5451     (clear-stream $_test-output-buffered-file->buffer)
 5452     #
 5453     (write _test-input-stream "fn foo {\n")
 5454     (write _test-input-stream "  {\n")
 5455     (write _test-input-stream "    var x: int\n")
 5456     (write _test-input-stream "    {\n")
 5457     (write _test-input-stream "      var y: int\n")
 5458     (write _test-input-stream "      break\n")
 5459     (write _test-input-stream "      increment x\n")
 5460     (write _test-input-stream "    }\n")
 5461     (write _test-input-stream "  }\n")
 5462     (write _test-input-stream "}\n")
 5463     # convert
 5464     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5465     (flush _test-output-buffered-file)
 5466 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5472     # check output
 5473     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-unconditional-break-and-local-vars/0")
 5474     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-unconditional-break-and-local-vars/1")
 5475     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-unconditional-break-and-local-vars/2")
 5476     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-unconditional-break-and-local-vars/3")
 5477     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-unconditional-break-and-local-vars/4")
 5478     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-unconditional-break-and-local-vars/5")
 5479     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-unconditional-break-and-local-vars/6")
 5480     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-unconditional-break-and-local-vars/7")
 5481     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-unconditional-break-and-local-vars/8")
 5482     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-unconditional-break-and-local-vars/9")
 5483     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-unconditional-break-and-local-vars/10")
 5484     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-unconditional-break-and-local-vars/11")
 5485     (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")
 5486     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-unconditional-break-and-local-vars/13")
 5487     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-unconditional-break-and-local-vars/14")
 5488     (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")
 5489     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-unconditional-break-and-local-vars/16")
 5490     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-unconditional-break-and-local-vars/17")
 5491     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-unconditional-break-and-local-vars/18")
 5492     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-unconditional-break-and-local-vars/19")
 5493     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-unconditional-break-and-local-vars/20")
 5494     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-unconditional-break-and-local-vars/21")
 5495     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-unconditional-break-and-local-vars/22")
 5496     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-unconditional-break-and-local-vars/23")
 5497     # . epilogue
 5498     89/<- %esp 5/r32/ebp
 5499     5d/pop-to-ebp
 5500     c3/return
 5501 
 5502 test-convert-function-with-nonlocal-unconditional-loop-and-local-vars:
 5503     # . prologue
 5504     55/push-ebp
 5505     89/<- %ebp 4/r32/esp
 5506     # setup
 5507     (clear-stream _test-input-stream)
 5508     (clear-stream $_test-input-buffered-file->buffer)
 5509     (clear-stream _test-output-stream)
 5510     (clear-stream $_test-output-buffered-file->buffer)
 5511     #
 5512     (write _test-input-stream "fn foo {\n")
 5513     (write _test-input-stream "  a: {\n")
 5514     (write _test-input-stream "    var x: int\n")
 5515     (write _test-input-stream "    {\n")
 5516     (write _test-input-stream "      var y: int\n")
 5517     (write _test-input-stream "      loop a\n")
 5518     (write _test-input-stream "      increment x\n")
 5519     (write _test-input-stream "    }\n")
 5520     (write _test-input-stream "  }\n")
 5521     (write _test-input-stream "}\n")
 5522     # convert
 5523     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5524     (flush _test-output-buffered-file)
 5525 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5531     # check output
 5532     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/0")
 5533     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/1")
 5534     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/2")
 5535     (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")
 5536     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/4")
 5537     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/5")
 5538     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/6")
 5539     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/7")
 5540     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/8")
 5541     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/9")
 5542     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/10")
 5543     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/11")
 5544     (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")
 5545     (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")
 5546     (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")
 5547     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/15")
 5548     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/16")
 5549     (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")
 5550     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/18")
 5551     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/19")
 5552     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/20")
 5553     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/21")
 5554     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/22")
 5555     (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")
 5556     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/24")
 5557     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/25")
 5558     # . epilogue
 5559     89/<- %esp 5/r32/ebp
 5560     5d/pop-to-ebp
 5561     c3/return
 5562 
 5563 test-convert-function-with-local-array-var-in-mem:
 5564     # . prologue
 5565     55/push-ebp
 5566     89/<- %ebp 4/r32/esp
 5567     # setup
 5568     (clear-stream _test-input-stream)
 5569     (clear-stream $_test-input-buffered-file->buffer)
 5570     (clear-stream _test-output-stream)
 5571     (clear-stream $_test-output-buffered-file->buffer)
 5572     #
 5573     (write _test-input-stream "fn foo {\n")
 5574     (write _test-input-stream "  var x: (array int 3)\n")
 5575     (write _test-input-stream "}\n")
 5576     # convert
 5577     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5578     (flush _test-output-buffered-file)
 5579 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5585     # check output
 5586     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-array-var-in-mem/0")
 5587     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-array-var-in-mem/1")
 5588     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-array-var-in-mem/2")
 5589     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-array-var-in-mem/3")
 5590     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-array-var-in-mem/4")
 5591     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-array-var-in-mem/5")
 5592     # define x
 5593     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x0000000c)"  "F - test-convert-function-with-local-array-var-in-mem/7")
 5594     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"  "F - test-convert-function-with-local-array-var-in-mem/8")
 5595     # reclaim x
 5596     (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")
 5597     #
 5598     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-array-var-in-mem/10")
 5599     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-array-var-in-mem/11")
 5600     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-array-var-in-mem/12")
 5601     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-array-var-in-mem/13")
 5602     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-array-var-in-mem/14")
 5603     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-array-var-in-mem/15")
 5604     # . epilogue
 5605     89/<- %esp 5/r32/ebp
 5606     5d/pop-to-ebp
 5607     c3/return
 5608 
 5609 test-array-size-in-hex:
 5610     # . prologue
 5611     55/push-ebp
 5612     89/<- %ebp 4/r32/esp
 5613     # setup
 5614     (clear-stream _test-input-stream)
 5615     (clear-stream $_test-input-buffered-file->buffer)
 5616     (clear-stream _test-output-stream)
 5617     (clear-stream $_test-output-buffered-file->buffer)
 5618     (clear-stream _test-error-stream)
 5619     (clear-stream $_test-error-buffered-file->buffer)
 5620     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 5621     68/push 0/imm32
 5622     68/push 0/imm32
 5623     89/<- %edx 4/r32/esp
 5624     (tailor-exit-descriptor %edx 0x10)
 5625     #
 5626     (write _test-input-stream "fn foo {\n")
 5627     (write _test-input-stream "  var x: (array int 10)\n")
 5628     (write _test-input-stream "}\n")
 5629     # convert
 5630     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 5631     # registers except esp clobbered at this point
 5632     # restore ed
 5633     89/<- %edx 4/r32/esp
 5634     (flush _test-output-buffered-file)
 5635     (flush _test-error-buffered-file)
 5636 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 5642     # check output
 5643     (check-stream-equal _test-output-stream  ""  "F - test-array-size-in-hex: output should be empty")
 5644     (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")
 5645     # check that stop(1) was called
 5646     (check-ints-equal *(edx+4) 2 "F - test-array-size-in-hex: exit status")
 5647     # don't restore from ebp
 5648     81 0/subop/add %esp 8/imm32
 5649     # . epilogue
 5650     5d/pop-to-ebp
 5651     c3/return
 5652 
 5653 test-array-size-with-metadata:
 5654     # . prologue
 5655     55/push-ebp
 5656     89/<- %ebp 4/r32/esp
 5657     # setup
 5658     (clear-stream _test-input-stream)
 5659     (clear-stream $_test-input-buffered-file->buffer)
 5660     (clear-stream _test-output-stream)
 5661     (clear-stream $_test-output-buffered-file->buffer)
 5662     #
 5663     (write _test-input-stream "fn foo {\n")
 5664     (write _test-input-stream "  var x: (array int 3/bar)\n")
 5665     (write _test-input-stream "}\n")
 5666     # convert
 5667     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5668     (flush _test-output-buffered-file)
 5669 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5675     # no errors
 5676     # . epilogue
 5677     89/<- %esp 5/r32/ebp
 5678     5d/pop-to-ebp
 5679     c3/return
 5680 
 5681 test-convert-function-with-populate:
 5682     # . prologue
 5683     55/push-ebp
 5684     89/<- %ebp 4/r32/esp
 5685     # setup
 5686     (clear-stream _test-input-stream)
 5687     (clear-stream $_test-input-buffered-file->buffer)
 5688     (clear-stream _test-output-stream)
 5689     (clear-stream $_test-output-buffered-file->buffer)
 5690     #
 5691     (write _test-input-stream "fn foo {\n")
 5692     (write _test-input-stream "  var x/ecx: (addr handle array int) <- copy 0\n")
 5693     (write _test-input-stream "  populate x, 7\n")
 5694     (write _test-input-stream "}\n")
 5695     # convert
 5696     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5697     (flush _test-output-buffered-file)
 5698 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5704     # check output
 5705     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-populate/0")
 5706     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-populate/1")
 5707     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-populate/2")
 5708     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-populate/3")
 5709     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-populate/4")
 5710     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-populate/5")
 5711     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-populate/6")
 5712     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-function-with-populate/7")
 5713     (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)
 5714     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-populate/9")
 5715     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-populate/10")
 5716     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-populate/11")
 5717     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-populate/12")
 5718     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-populate/13")
 5719     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-populate/14")
 5720     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-populate/15")
 5721     # . epilogue
 5722     89/<- %esp 5/r32/ebp
 5723     5d/pop-to-ebp
 5724     c3/return
 5725 
 5726 # special-case for size(byte) when allocating array
 5727 test-convert-function-with-local-array-of-bytes-in-mem:
 5728     # . prologue
 5729     55/push-ebp
 5730     89/<- %ebp 4/r32/esp
 5731     # setup
 5732     (clear-stream _test-input-stream)
 5733     (clear-stream $_test-input-buffered-file->buffer)
 5734     (clear-stream _test-output-stream)
 5735     (clear-stream $_test-output-buffered-file->buffer)
 5736     #
 5737     (write _test-input-stream "fn foo {\n")
 5738     (write _test-input-stream "  var x: (array byte 3)\n")
 5739     (write _test-input-stream "}\n")
 5740     # convert
 5741     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5742     (flush _test-output-buffered-file)
 5743 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5749     # check output
 5750     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-array-of-bytes-in-mem/0")
 5751     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-array-of-bytes-in-mem/1")
 5752     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-array-of-bytes-in-mem/2")
 5753     (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")
 5754     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-array-of-bytes-in-mem/4")
 5755     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-array-of-bytes-in-mem/5")
 5756     # define x
 5757     (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")
 5758     (check-next-stream-line-equal _test-output-stream "    68/push 0x00000003/imm32"  "F - test-convert-function-with-local-array-of-bytes-in-mem/8")
 5759     # reclaim x
 5760     (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")
 5761     #
 5762     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-array-of-bytes-in-mem/10")
 5763     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-array-of-bytes-in-mem/11")
 5764     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-array-of-bytes-in-mem/12")
 5765     (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")
 5766     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-array-of-bytes-in-mem/14")
 5767     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-array-of-bytes-in-mem/15")
 5768     # . epilogue
 5769     89/<- %esp 5/r32/ebp
 5770     5d/pop-to-ebp
 5771     c3/return
 5772 
 5773 test-convert-address:
 5774     # . prologue
 5775     55/push-ebp
 5776     89/<- %ebp 4/r32/esp
 5777     # setup
 5778     (clear-stream _test-input-stream)
 5779     (clear-stream $_test-input-buffered-file->buffer)
 5780     (clear-stream _test-output-stream)
 5781     (clear-stream $_test-output-buffered-file->buffer)
 5782     #
 5783     (write _test-input-stream "fn foo {\n")
 5784     (write _test-input-stream "  var a: int\n")
 5785     (write _test-input-stream "  var b/eax: (addr int) <- address a\n")
 5786     (write _test-input-stream "}\n")
 5787     # convert
 5788     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5789     (flush _test-output-buffered-file)
 5790 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5796     # check output
 5797     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-address/0")
 5798     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-address/1")
 5799     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-address/2")
 5800     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-address/3")
 5801     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-address/4")
 5802     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-address/5")
 5803     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-address/6")
 5804     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-address/7")
 5805     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp+0xfffffffc) 0x00000000/r32"  "F - test-convert-address/8")
 5806     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-address/9")
 5807     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-address/10")
 5808     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-address/11")
 5809     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-address/12")
 5810     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-address/13")
 5811     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-address/14")
 5812     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-address/15")
 5813     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-address/16")
 5814     # . epilogue
 5815     89/<- %esp 5/r32/ebp
 5816     5d/pop-to-ebp
 5817     c3/return
 5818 
 5819 test-convert-floating-point-convert:
 5820     # . prologue
 5821     55/push-ebp
 5822     89/<- %ebp 4/r32/esp
 5823     # setup
 5824     (clear-stream _test-input-stream)
 5825     (clear-stream $_test-input-buffered-file->buffer)
 5826     (clear-stream _test-output-stream)
 5827     (clear-stream $_test-output-buffered-file->buffer)
 5828     #
 5829     (write _test-input-stream "fn foo {\n")
 5830     (write _test-input-stream "  var a/eax: int <- copy 0\n")
 5831     (write _test-input-stream "  var b/xmm1: float <- convert a\n")
 5832     (write _test-input-stream "}\n")
 5833     # convert
 5834     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5835     (flush _test-output-buffered-file)
 5836 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5842     # check output
 5843     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-floating-point-convert/0")
 5844     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-floating-point-convert/1")
 5845     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-floating-point-convert/2")
 5846     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-floating-point-convert/3")
 5847     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-floating-point-convert/4")
 5848     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-floating-point-convert/5")
 5849     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-floating-point-convert/6")
 5850     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"  "F - test-convert-floating-point-convert/7")
 5851     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"  "F - test-convert-floating-point-convert/8")
 5852     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 1/x32"  "F - test-convert-floating-point-convert/9")
 5853     (check-next-stream-line-equal _test-output-stream "    f3 0f 2a/convert-to-float %eax 0x00000001/x32"  "F - test-convert-floating-point-convert/10")
 5854     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 1/x32"  "F - test-convert-floating-point-convert/11")
 5855     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-floating-point-convert/12")
 5856     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-floating-point-convert/13")
 5857     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-floating-point-convert/14")
 5858     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-floating-point-convert/15")
 5859     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-floating-point-convert/16")
 5860     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-floating-point-convert/17")
 5861     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-floating-point-convert/18")
 5862     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-floating-point-convert/19")
 5863     # . epilogue
 5864     89/<- %esp 5/r32/ebp
 5865     5d/pop-to-ebp
 5866     c3/return
 5867 
 5868 test-convert-floating-point-convert-2:
 5869     # . prologue
 5870     55/push-ebp
 5871     89/<- %ebp 4/r32/esp
 5872     # setup
 5873     (clear-stream _test-input-stream)
 5874     (clear-stream $_test-input-buffered-file->buffer)
 5875     (clear-stream _test-output-stream)
 5876     (clear-stream $_test-output-buffered-file->buffer)
 5877     #
 5878     (write _test-input-stream "fn foo {\n")
 5879     (write _test-input-stream "  var a/eax: int <- copy 0\n")
 5880     (write _test-input-stream "  var b/xmm1: float <- convert a\n")
 5881     (write _test-input-stream "  a <- convert b\n")
 5882     (write _test-input-stream "}\n")
 5883     # convert
 5884     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5885     (flush _test-output-buffered-file)
 5886 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5892     # check output
 5893     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-floating-point-convert-2/0")
 5894     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-floating-point-convert-2/1")
 5895     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-floating-point-convert-2/2")
 5896     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-floating-point-convert-2/3")
 5897     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-floating-point-convert-2/4")
 5898     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-floating-point-convert-2/5")
 5899     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-floating-point-convert-2/6")
 5900     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"  "F - test-convert-floating-point-convert-2/7")
 5901     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"  "F - test-convert-floating-point-convert-2/8")
 5902     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 1/x32"  "F - test-convert-floating-point-convert-2/9")
 5903     (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")
 5904     (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")
 5905     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 1/x32"  "F - test-convert-floating-point-convert-2/12")
 5906     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-floating-point-convert-2/13")
 5907     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-floating-point-convert-2/14")
 5908     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-floating-point-convert-2/15")
 5909     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-floating-point-convert-2/16")
 5910     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-floating-point-convert-2/17")
 5911     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-floating-point-convert-2/18")
 5912     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-floating-point-convert-2/19")
 5913     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-floating-point-convert-2/20")
 5914     # . epilogue
 5915     89/<- %esp 5/r32/ebp
 5916     5d/pop-to-ebp
 5917     c3/return
 5918 
 5919 test-convert-floating-point-operation:
 5920     # . prologue
 5921     55/push-ebp
 5922     89/<- %ebp 4/r32/esp
 5923     # setup
 5924     (clear-stream _test-input-stream)
 5925     (clear-stream $_test-input-buffered-file->buffer)
 5926     (clear-stream _test-output-stream)
 5927     (clear-stream $_test-output-buffered-file->buffer)
 5928     #
 5929     (write _test-input-stream "fn f {\n")
 5930     (write _test-input-stream "  var m: float\n")
 5931     (write _test-input-stream "  var x/xmm1: float <- copy m\n")
 5932     (write _test-input-stream "  var y/xmm5: float <- copy m\n")
 5933     (write _test-input-stream "  x <- copy y\n")
 5934     (write _test-input-stream "  copy-to m, y\n")
 5935     (write _test-input-stream "  x <- add y\n")
 5936     (write _test-input-stream "  x <- add m\n")
 5937     (write _test-input-stream "  x <- subtract y\n")
 5938     (write _test-input-stream "  x <- subtract m\n")
 5939     (write _test-input-stream "  x <- multiply y\n")
 5940     (write _test-input-stream "  x <- multiply m\n")
 5941     (write _test-input-stream "  x <- divide y\n")
 5942     (write _test-input-stream "  x <- divide m\n")
 5943     (write _test-input-stream "  x <- reciprocal y\n")
 5944     (write _test-input-stream "  x <- reciprocal m\n")
 5945     (write _test-input-stream "  x <- square-root y\n")
 5946     (write _test-input-stream "  x <- square-root m\n")
 5947     (write _test-input-stream "  x <- inverse-square-root y\n")
 5948     (write _test-input-stream "  x <- inverse-square-root m\n")
 5949     (write _test-input-stream "  x <- max y\n")
 5950     (write _test-input-stream "  x <- max m\n")
 5951     (write _test-input-stream "  x <- min y\n")
 5952     (write _test-input-stream "  x <- min m\n")
 5953     (write _test-input-stream "  compare x, y\n")
 5954     (write _test-input-stream "  compare x, m\n")
 5955     (write _test-input-stream "}\n")
 5956     # convert
 5957     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5958     (flush _test-output-buffered-file)
 5959 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5965     # check output
 5966     (check-next-stream-line-equal _test-output-stream "f:"                                                                     "F - test-convert-floating-point-operation/0")
 5967     (check-next-stream-line-equal _test-output-stream "  # . prologue"                                                         "F - test-convert-floating-point-operation/1")
 5968     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                                                          "F - test-convert-floating-point-operation/2")
 5969     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                                                 "F - test-convert-floating-point-operation/3")
 5970     (check-next-stream-line-equal _test-output-stream "  {"                                                                    "F - test-convert-floating-point-operation/4")
 5971     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"                                                    "F - test-convert-floating-point-operation/5")
 5972     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"                                                    "F - test-convert-floating-point-operation/6")
 5973     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"                                   "F - test-convert-floating-point-operation/7")
 5974     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 1/x32"                                             "F - test-convert-floating-point-operation/8")
 5975     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/copy *(ebp+0xfffffffc) 0x00000001/x32"                     "F - test-convert-floating-point-operation/9")
 5976     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"                                   "F - test-convert-floating-point-operation/10")
 5977     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 5/x32"                                             "F - test-convert-floating-point-operation/11")
 5978     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/copy *(ebp+0xfffffffc) 0x00000005/x32"                     "F - test-convert-floating-point-operation/12")
 5979     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/copy %xmm1 0x00000005/x32"                                 "F - test-convert-floating-point-operation/13")
 5980     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/copy *(ebp+0xfffffffc) 0x00000005/x32"                     "F - test-convert-floating-point-operation/14")
 5981     (check-next-stream-line-equal _test-output-stream "    f3 0f 58/add %xmm5 0x00000001/x32"                                  "F - test-convert-floating-point-operation/15")
 5982     (check-next-stream-line-equal _test-output-stream "    f3 0f 58/add *(ebp+0xfffffffc) 0x00000001/x32"                      "F - test-convert-floating-point-operation/16")
 5983     (check-next-stream-line-equal _test-output-stream "    f3 0f 5c/subtract %xmm5 0x00000001/x32"                             "F - test-convert-floating-point-operation/17")
 5984     (check-next-stream-line-equal _test-output-stream "    f3 0f 5c/subtract *(ebp+0xfffffffc) 0x00000001/x32"                 "F - test-convert-floating-point-operation/18")
 5985     (check-next-stream-line-equal _test-output-stream "    f3 0f 59/multiply %xmm5 0x00000001/x32"                             "F - test-convert-floating-point-operation/19")
 5986     (check-next-stream-line-equal _test-output-stream "    f3 0f 59/multiply *(ebp+0xfffffffc) 0x00000001/x32"                 "F - test-convert-floating-point-operation/20")
 5987     (check-next-stream-line-equal _test-output-stream "    f3 0f 5e/divide %xmm5 0x00000001/x32"                               "F - test-convert-floating-point-operation/21")
 5988     (check-next-stream-line-equal _test-output-stream "    f3 0f 5e/divide *(ebp+0xfffffffc) 0x00000001/x32"                   "F - test-convert-floating-point-operation/22")
 5989     (check-next-stream-line-equal _test-output-stream "    f3 0f 53/reciprocal %xmm5 0x00000001/x32"                           "F - test-convert-floating-point-operation/23")
 5990     (check-next-stream-line-equal _test-output-stream "    f3 0f 53/reciprocal *(ebp+0xfffffffc) 0x00000001/x32"               "F - test-convert-floating-point-operation/24")
 5991     (check-next-stream-line-equal _test-output-stream "    f3 0f 51/square-root %xmm5 0x00000001/x32"                          "F - test-convert-floating-point-operation/25")
 5992     (check-next-stream-line-equal _test-output-stream "    f3 0f 51/square-root *(ebp+0xfffffffc) 0x00000001/x32"              "F - test-convert-floating-point-operation/26")
 5993     (check-next-stream-line-equal _test-output-stream "    f3 0f 52/inverse-square-root %xmm5 0x00000001/x32"                  "F - test-convert-floating-point-operation/27")
 5994     (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")
 5995     (check-next-stream-line-equal _test-output-stream "    f3 0f 5f/max %xmm5 0x00000001/x32"                                  "F - test-convert-floating-point-operation/29")
 5996     (check-next-stream-line-equal _test-output-stream "    f3 0f 5f/max *(ebp+0xfffffffc) 0x00000001/x32"                      "F - test-convert-floating-point-operation/30")
 5997     (check-next-stream-line-equal _test-output-stream "    f3 0f 5d/min %xmm5 0x00000001/x32"                                  "F - test-convert-floating-point-operation/31")
 5998     (check-next-stream-line-equal _test-output-stream "    f3 0f 5d/min *(ebp+0xfffffffc) 0x00000001/x32"                      "F - test-convert-floating-point-operation/32")
 5999     (check-next-stream-line-equal _test-output-stream "    0f 2f/compare %xmm5 0x00000001/x32"                                 "F - test-convert-floating-point-operation/33")
 6000     (check-next-stream-line-equal _test-output-stream "    0f 2f/compare *(ebp+0xfffffffc) 0x00000001/x32"                     "F - test-convert-floating-point-operation/34")
 6001     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 5/x32"                                             "F - test-convert-floating-point-operation/35")
 6002     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"                                        "F - test-convert-floating-point-operation/36")
 6003     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 1/x32"                                             "F - test-convert-floating-point-operation/37")
 6004     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"                                        "F - test-convert-floating-point-operation/38")
 6005     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"                               "F - test-convert-floating-point-operation/39")
 6006     (check-next-stream-line-equal _test-output-stream "  }"                                                                    "F - test-convert-floating-point-operation/40")
 6007     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"                                                   "F - test-convert-floating-point-operation/41")
 6008     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                                                         "F - test-convert-floating-point-operation/42")
 6009     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                                                 "F - test-convert-floating-point-operation/43")
 6010     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                                                        "F - test-convert-floating-point-operation/44")
 6011     (check-next-stream-line-equal _test-output-stream "  c3/return"                                                            "F - test-convert-floating-point-operation/45")
 6012     # . epilogue
 6013     89/<- %esp 5/r32/ebp
 6014     5d/pop-to-ebp
 6015     c3/return
 6016 
 6017 test-convert-floating-point-dereferenced:
 6018     # . prologue
 6019     55/push-ebp
 6020     89/<- %ebp 4/r32/esp
 6021     # setup
 6022     (clear-stream _test-input-stream)
 6023     (clear-stream $_test-input-buffered-file->buffer)
 6024     (clear-stream _test-output-stream)
 6025     (clear-stream $_test-output-buffered-file->buffer)
 6026     #
 6027     (write _test-input-stream "fn f {\n")
 6028     (write _test-input-stream "  var m: float\n")
 6029     (write _test-input-stream "  var x/xmm1: float <- copy m\n")
 6030     (write _test-input-stream "  var y/eax: (addr float) <- copy 0\n")
 6031     (write _test-input-stream "  x <- multiply *y\n")
 6032     (write _test-input-stream "}\n")
 6033     # convert
 6034     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6035     (flush _test-output-buffered-file)
 6036 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6042     # check output
 6043     (check-next-stream-line-equal _test-output-stream "f:"                                                                     "F - test-convert-floating-point-dereferenced/0")
 6044     (check-next-stream-line-equal _test-output-stream "  # . prologue"                                                         "F - test-convert-floating-point-dereferenced/1")
 6045     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                                                          "F - test-convert-floating-point-dereferenced/2")
 6046     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                                                 "F - test-convert-floating-point-dereferenced/3")
 6047     (check-next-stream-line-equal _test-output-stream "  {"                                                                    "F - test-convert-floating-point-dereferenced/4")
 6048     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"                                                    "F - test-convert-floating-point-dereferenced/5")
 6049     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"                                                    "F - test-convert-floating-point-dereferenced/6")
 6050     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"                                   "F - test-convert-floating-point-dereferenced/7")
 6051     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 1/x32"                                             "F - test-convert-floating-point-dereferenced/8")
 6052     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/copy *(ebp+0xfffffffc) 0x00000001/x32"                     "F - test-convert-floating-point-dereferenced/9")
 6053     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                                               "F - test-convert-floating-point-dereferenced/10")
 6054     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                                             "F - test-convert-floating-point-dereferenced/11")
 6055     (check-next-stream-line-equal _test-output-stream "    f3 0f 59/multiply *eax 0x00000001/x32"                              "F - test-convert-floating-point-dereferenced/12")
 6056     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                                                "F - test-convert-floating-point-dereferenced/13")
 6057     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 1/x32"                                             "F - test-convert-floating-point-dereferenced/14")
 6058     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"                                        "F - test-convert-floating-point-dereferenced/15")
 6059     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"                               "F - test-convert-floating-point-dereferenced/16")
 6060     (check-next-stream-line-equal _test-output-stream "  }"                                                                    "F - test-convert-floating-point-dereferenced/17")
 6061     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"                                                   "F - test-convert-floating-point-dereferenced/18")
 6062     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                                                         "F - test-convert-floating-point-dereferenced/19")
 6063     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                                                 "F - test-convert-floating-point-dereferenced/20")
 6064     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                                                        "F - test-convert-floating-point-dereferenced/21")
 6065     (check-next-stream-line-equal _test-output-stream "  c3/return"                                                            "F - test-convert-floating-point-dereferenced/22")
 6066     # . epilogue
 6067     89/<- %esp 5/r32/ebp
 6068     5d/pop-to-ebp
 6069     c3/return
 6070 
 6071 test-convert-length-of-array:
 6072     # . prologue
 6073     55/push-ebp
 6074     89/<- %ebp 4/r32/esp
 6075     # setup
 6076     (clear-stream _test-input-stream)
 6077     (clear-stream $_test-input-buffered-file->buffer)
 6078     (clear-stream _test-output-stream)
 6079     (clear-stream $_test-output-buffered-file->buffer)
 6080     #
 6081     (write _test-input-stream "fn foo a: (addr array int) {\n")
 6082     (write _test-input-stream "  var b/eax: (addr array int) <- copy a\n")
 6083     (write _test-input-stream "  var c/eax: int <- length b\n")
 6084     (write _test-input-stream "}\n")
 6085     # convert
 6086     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6087     (flush _test-output-buffered-file)
 6088 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6094     # check output
 6095     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array/0")
 6096     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array/1")
 6097     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array/2")
 6098     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array/3")
 6099     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array/4")
 6100     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array/5")
 6101     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array/6")
 6102     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-length-of-array/7")
 6103     (check-next-stream-line-equal _test-output-stream "    8b/-> *eax 0x00000000/r32"  "F - test-convert-length-of-array/8")
 6104     (check-next-stream-line-equal _test-output-stream "    c1/shift 5/subop/>> %eax 0x00000002/imm8"  "F - test-convert-length-of-array/9")
 6105     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array/10")
 6106     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array/11")
 6107     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array/12")
 6108     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array/13")
 6109     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array/14")
 6110     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array/15")
 6111     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array/16")
 6112     # . epilogue
 6113     89/<- %esp 5/r32/ebp
 6114     5d/pop-to-ebp
 6115     c3/return
 6116 
 6117 # special-case for size(byte) when computing array length
 6118 test-convert-length-of-array-of-bytes:
 6119     # . prologue
 6120     55/push-ebp
 6121     89/<- %ebp 4/r32/esp
 6122     # setup
 6123     (clear-stream _test-input-stream)
 6124     (clear-stream $_test-input-buffered-file->buffer)
 6125     (clear-stream _test-output-stream)
 6126     (clear-stream $_test-output-buffered-file->buffer)
 6127     #
 6128     (write _test-input-stream "fn foo a: (addr array byte) {\n")
 6129     (write _test-input-stream "  var b/eax: (addr array byte) <- copy a\n")
 6130     (write _test-input-stream "  var c/eax: int <- length b\n")
 6131     (write _test-input-stream "}\n")
 6132     # convert
 6133     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6134     (flush _test-output-buffered-file)
 6135 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6141     # check output
 6142     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-bytes/0")
 6143     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-bytes/1")
 6144     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-bytes/2")
 6145     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array-of-bytes/3")
 6146     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-bytes/4")
 6147     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-bytes/5")
 6148     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array-of-bytes/6")
 6149     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-length-of-array-of-bytes/7")
 6150     (check-next-stream-line-equal _test-output-stream "    8b/-> *eax 0x00000000/r32"  "F - test-convert-length-of-array-of-bytes/8")
 6151     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array-of-bytes/9")
 6152     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-bytes/10")
 6153     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-bytes/11")
 6154     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-bytes/12")
 6155     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array-of-bytes/13")
 6156     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array-of-bytes/14")
 6157     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-bytes/15")
 6158     # . epilogue
 6159     89/<- %esp 5/r32/ebp
 6160     5d/pop-to-ebp
 6161     c3/return
 6162 
 6163 test-convert-length-of-array-on-stack:
 6164     # . prologue
 6165     55/push-ebp
 6166     89/<- %ebp 4/r32/esp
 6167     # setup
 6168     (clear-stream _test-input-stream)
 6169     (clear-stream $_test-input-buffered-file->buffer)
 6170     (clear-stream _test-output-stream)
 6171     (clear-stream $_test-output-buffered-file->buffer)
 6172     #
 6173     (write _test-input-stream "fn foo {\n")
 6174     (write _test-input-stream "  var a: (array int 3)\n")
 6175     (write _test-input-stream "  var b/eax: int <- length a\n")
 6176     (write _test-input-stream "}\n")
 6177     # convert
 6178     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6179     (flush _test-output-buffered-file)
 6180 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6186     # check output
 6187     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-on-stack/0")
 6188     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-on-stack/1")
 6189     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-on-stack/2")
 6190     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array-on-stack/3")
 6191     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-on-stack/4")
 6192     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-on-stack/5")
 6193     # define x
 6194     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x0000000c)"  "F - test-convert-length-of-array-on-stack/6")
 6195     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"  "F - test-convert-length-of-array-on-stack/7")
 6196     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array-on-stack/8")
 6197     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0xfffffff0) 0x00000000/r32"  "F - test-convert-length-of-array-on-stack/9")
 6198     (check-next-stream-line-equal _test-output-stream "    c1/shift 5/subop/>> %eax 0x00000002/imm8"  "F - test-convert-length-of-array-on-stack/10")
 6199     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array-on-stack/11")
 6200     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000010/imm32"  "F - test-convert-length-of-array-on-stack/12")
 6201     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-on-stack/13")
 6202     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-on-stack/14")
 6203     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-on-stack/15")
 6204     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array-on-stack/16")
 6205     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array-on-stack/17")
 6206     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-on-stack/18")
 6207     # . epilogue
 6208     89/<- %esp 5/r32/ebp
 6209     5d/pop-to-ebp
 6210     c3/return
 6211 
 6212 test-reg-var-def-with-read-of-same-register:
 6213     # . prologue
 6214     55/push-ebp
 6215     89/<- %ebp 4/r32/esp
 6216     # setup
 6217     (clear-stream _test-input-stream)
 6218     (clear-stream $_test-input-buffered-file->buffer)
 6219     (clear-stream _test-output-stream)
 6220     (clear-stream $_test-output-buffered-file->buffer)
 6221     (clear-stream _test-error-stream)
 6222     (clear-stream $_test-error-buffered-file->buffer)
 6223     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)  # bytes of args in call to convert-mu
 6224     68/push 0/imm32
 6225     68/push 0/imm32
 6226     89/<- %edx 4/r32/esp
 6227     (tailor-exit-descriptor %edx 0x10)
 6228     #
 6229     (write _test-input-stream "fn foo {\n")
 6230     (write _test-input-stream "  var x/eax: int <- copy 3\n")
 6231     (write _test-input-stream "  var y/eax: int <- add x\n")
 6232     (write _test-input-stream "}\n")
 6233     # convert
 6234     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6235     # registers except esp could be clobbered at this point (though they shouldn't be)
 6236     # restore ed
 6237     89/<- %edx 4/r32/esp
 6238     (flush _test-output-buffered-file)
 6239     (flush _test-error-buffered-file)
 6240 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6246 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 6252     (check-stream-equal _test-error-stream  ""  "F - test-reg-var-def-with-read-of-same-register: error stream should be empty")
 6253     # check output
 6254     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-reg-var-def-with-read-of-same-register/0")
 6255     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-reg-var-def-with-read-of-same-register/1")
 6256     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-reg-var-def-with-read-of-same-register/2")
 6257     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-reg-var-def-with-read-of-same-register/3")
 6258     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-reg-var-def-with-read-of-same-register/4")
 6259     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-reg-var-def-with-read-of-same-register/5")
 6260     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-reg-var-def-with-read-of-same-register/6")
 6261     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 3/imm32"                  "F - test-reg-var-def-with-read-of-same-register/7")
 6262     (check-next-stream-line-equal _test-output-stream "    01/add-to %eax 0x00000000/r32"           "F - test-reg-var-def-with-read-of-same-register/8")
 6263     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-reg-var-def-with-read-of-same-register/9")
 6264     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-reg-var-def-with-read-of-same-register/10")
 6265     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-reg-var-def-with-read-of-same-register/11")
 6266     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-reg-var-def-with-read-of-same-register/12")
 6267     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-reg-var-def-with-read-of-same-register/13")
 6268     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-reg-var-def-with-read-of-same-register/14")
 6269     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-reg-var-def-with-read-of-same-register/15")
 6270     # don't restore from ebp
 6271     81 0/subop/add %esp 8/imm32
 6272     # . epilogue
 6273     5d/pop-to-ebp
 6274     c3/return
 6275 
 6276 test-convert-index-into-array:
 6277     # . prologue
 6278     55/push-ebp
 6279     89/<- %ebp 4/r32/esp
 6280     # setup
 6281     (clear-stream _test-input-stream)
 6282     (clear-stream $_test-input-buffered-file->buffer)
 6283     (clear-stream _test-output-stream)
 6284     (clear-stream $_test-output-buffered-file->buffer)
 6285     #
 6286     (write _test-input-stream "fn foo {\n")
 6287     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
 6288     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
 6289     (write _test-input-stream "  var x/eax: (addr int) <- index arr, idx\n")
 6290     (write _test-input-stream "}\n")
 6291     # convert
 6292     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6293     (flush _test-output-buffered-file)
 6294 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6300     # check output
 6301     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array/0")
 6302     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array/1")
 6303     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array/2")
 6304     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array/3")
 6305     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array/4")
 6306     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array/5")
 6307     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array/6")
 6308     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array/7")
 6309     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array/8")
 6310     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-index-into-array/9")
 6311     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds %ecx 0x00000004 *eax \"foo\" \"arr\")"  "F - test-convert-index-into-array/10")
 6312     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx<<0x00000002 + 4) 0x00000000/r32"  "F - test-convert-index-into-array/11")
 6313     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array/12")
 6314     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array/13")
 6315     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array/14")
 6316     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array/15")
 6317     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array/16")
 6318     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array/17")
 6319     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array/18")
 6320     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array/19")
 6321     # . epilogue
 6322     89/<- %esp 5/r32/ebp
 6323     5d/pop-to-ebp
 6324     c3/return
 6325 
 6326 test-convert-index-into-array-of-bytes:
 6327     # . prologue
 6328     55/push-ebp
 6329     89/<- %ebp 4/r32/esp
 6330     # setup
 6331     (clear-stream _test-input-stream)
 6332     (clear-stream $_test-input-buffered-file->buffer)
 6333     (clear-stream _test-output-stream)
 6334     (clear-stream $_test-output-buffered-file->buffer)
 6335     #
 6336     (write _test-input-stream "fn foo {\n")
 6337     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
 6338     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
 6339     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, idx\n")
 6340     (write _test-input-stream "}\n")
 6341     # convert
 6342     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6343     (flush _test-output-buffered-file)
 6344 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6350     # check output
 6351     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes/0")
 6352     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes/1")
 6353     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes/2")
 6354     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-of-bytes/3")
 6355     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes/4")
 6356     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes/5")
 6357     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-of-bytes/6")
 6358     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array-of-bytes/7")
 6359     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-of-bytes/8")
 6360     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-index-into-array-of-bytes/9")
 6361     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds %ecx 0x00000001 *eax \"foo\" \"arr\")"  "F - test-convert-index-into-array-of-bytes/10")
 6362     (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")
 6363     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-of-bytes/12")
 6364     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes/13")
 6365     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes/14")
 6366     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes/15")
 6367     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes/16")
 6368     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes/17")
 6369     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes/18")
 6370     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes/19")
 6371     # . epilogue
 6372     89/<- %esp 5/r32/ebp
 6373     5d/pop-to-ebp
 6374     c3/return
 6375 
 6376 test-convert-index-into-array-with-literal:
 6377     # . prologue
 6378     55/push-ebp
 6379     89/<- %ebp 4/r32/esp
 6380     # setup
 6381     (clear-stream _test-input-stream)
 6382     (clear-stream $_test-input-buffered-file->buffer)
 6383     (clear-stream _test-output-stream)
 6384     (clear-stream $_test-output-buffered-file->buffer)
 6385     #
 6386     (write _test-input-stream "fn foo {\n")
 6387     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
 6388     (write _test-input-stream "  var x/eax: (addr int) <- index arr, 2\n")
 6389     (write _test-input-stream "}\n")
 6390     # convert
 6391     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6392     (flush _test-output-buffered-file)
 6393 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6399     # check output
 6400     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-with-literal/0")
 6401     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-with-literal/1")
 6402     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-with-literal/2")
 6403     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-with-literal/3")
 6404     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-with-literal/4")
 6405     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-with-literal/5")
 6406     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-with-literal/6")
 6407     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array-with-literal/7")
 6408     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds 2 0x00000004 *eax \"foo\" \"arr\")"  "F - test-convert-index-into-array-with-literal/8")
 6409                                                                                  # 2 * 4 bytes/elem + 4 bytes for size = offset 12
 6410     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + 0x0000000c) 0x00000000/r32"  "F - test-convert-index-into-array-with-literal/9")
 6411     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-with-literal/10")
 6412     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-with-literal/11")
 6413     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-with-literal/12")
 6414     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-with-literal/13")
 6415     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-with-literal/14")
 6416     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-with-literal/15")
 6417     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-with-literal/16")
 6418     # . epilogue
 6419     89/<- %esp 5/r32/ebp
 6420     5d/pop-to-ebp
 6421     c3/return
 6422 
 6423 test-convert-index-into-array-of-bytes-with-literal:
 6424     # . prologue
 6425     55/push-ebp
 6426     89/<- %ebp 4/r32/esp
 6427     # setup
 6428     (clear-stream _test-input-stream)
 6429     (clear-stream $_test-input-buffered-file->buffer)
 6430     (clear-stream _test-output-stream)
 6431     (clear-stream $_test-output-buffered-file->buffer)
 6432     #
 6433     (write _test-input-stream "fn foo {\n")
 6434     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
 6435     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, 2\n")
 6436     (write _test-input-stream "}\n")
 6437     # convert
 6438     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6439     (flush _test-output-buffered-file)
 6440 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6446     # check output
 6447     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-with-literal/0")
 6448     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-with-literal/1")
 6449     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-with-literal/2")
 6450     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-of-bytes-with-literal/3")
 6451     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-with-literal/4")
 6452     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-with-literal/5")
 6453     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-of-bytes-with-literal/6")
 6454     (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")
 6455     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds 2 0x00000001 *eax \"foo\" \"arr\")"  "F - test-convert-index-into-array-of-bytes-with-literal/8")
 6456                                                                                  # 2 * 1 byte/elem + 4 bytes for size = offset 6
 6457     (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")
 6458     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes-with-literal/9")
 6459     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-with-literal/10")
 6460     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-with-literal/11")
 6461     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-with-literal/12")
 6462     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes-with-literal/13")
 6463     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes-with-literal/14")
 6464     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-with-literal/15")
 6465     # . epilogue
 6466     89/<- %esp 5/r32/ebp
 6467     5d/pop-to-ebp
 6468     c3/return
 6469 
 6470 test-convert-index-into-array-on-stack:
 6471     # . prologue
 6472     55/push-ebp
 6473     89/<- %ebp 4/r32/esp
 6474     # setup
 6475     (clear-stream _test-input-stream)
 6476     (clear-stream $_test-input-buffered-file->buffer)
 6477     (clear-stream _test-output-stream)
 6478     (clear-stream $_test-output-buffered-file->buffer)
 6479     #
 6480     (write _test-input-stream "fn foo {\n")
 6481     (write _test-input-stream "  var arr: (array int 3)\n")
 6482     (write _test-input-stream "  var idx/eax: int <- copy 2\n")
 6483     (write _test-input-stream "  var x/eax: (addr int) <- index arr, idx\n")
 6484     (write _test-input-stream "}\n")
 6485     # convert
 6486     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6487     (flush _test-output-buffered-file)
 6488 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6494     # check output
 6495     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-on-stack/0")
 6496     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-on-stack/1")
 6497     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-on-stack/2")
 6498     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-on-stack/3")
 6499     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-on-stack/4")
 6500     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-on-stack/5")
 6501     # var arr
 6502     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x0000000c)"          "F - test-convert-index-into-array-on-stack/6")
 6503     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"                "F - test-convert-index-into-array-on-stack/7")
 6504     # var idx
 6505     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-on-stack/8")
 6506     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 2/imm32"                  "F - test-convert-index-into-array-on-stack/9")
 6507     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds %eax 0x00000004 *(ebp+0xfffffff0) \"foo\" \"arr\")"  "F - test-convert-index-into-array-on-stack/10")
 6508     # var x is at (ebp-0x10) + idx<<2 + 4 = ebp + idx<<2 - 0xc
 6509     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp + eax<<0x00000002 + 0xfffffff4) 0x00000000/r32"  "F - test-convert-index-into-array-on-stack/11")
 6510     # reclaim idx
 6511     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-on-stack/12")
 6512     # reclaim arr
 6513     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000010/imm32"    "F - test-convert-index-into-array-on-stack/13")
 6514     #
 6515     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-on-stack/14")
 6516     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-on-stack/15")
 6517     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-on-stack/16")
 6518     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-on-stack/17")
 6519     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-on-stack/18")
 6520     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-on-stack/19")
 6521     # . epilogue
 6522     89/<- %esp 5/r32/ebp
 6523     5d/pop-to-ebp
 6524     c3/return
 6525 
 6526 test-convert-index-into-array-on-stack-with-literal:
 6527     # . prologue
 6528     55/push-ebp
 6529     89/<- %ebp 4/r32/esp
 6530     # setup
 6531     (clear-stream _test-input-stream)
 6532     (clear-stream $_test-input-buffered-file->buffer)
 6533     (clear-stream _test-output-stream)
 6534     (clear-stream $_test-output-buffered-file->buffer)
 6535     #
 6536     (write _test-input-stream "fn foo {\n")
 6537     (write _test-input-stream "  var arr: (array int 3)\n")
 6538     (write _test-input-stream "  var x/eax: (addr int) <- index arr, 2\n")
 6539     (write _test-input-stream "}\n")
 6540     # convert
 6541     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6542     (flush _test-output-buffered-file)
 6543 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6549     # check output
 6550     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-on-stack-with-literal/0")
 6551     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-on-stack-with-literal/1")
 6552     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-on-stack-with-literal/2")
 6553     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-on-stack-with-literal/3")
 6554     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-on-stack-with-literal/4")
 6555     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-on-stack-with-literal/5")
 6556     # var arr
 6557     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x0000000c)"          "F - test-convert-index-into-array-on-stack-with-literal/6")
 6558     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"                "F - test-convert-index-into-array-on-stack-with-literal/7")
 6559     # var x
 6560     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-on-stack-with-literal/8")
 6561     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds 2 0x00000004 *(ebp+0xfffffff0) \"foo\" \"arr\")"  "F - test-convert-index-into-array-on-stack-with-literal/9")
 6562     # x is at (ebp-0x10) + 4 + 2*4 = ebp-4
 6563     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp + 0xfffffffc) 0x00000000/r32"  "F - test-convert-index-into-array-on-stack-with-literal/10")
 6564     # reclaim x
 6565     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-on-stack-with-literal/11")
 6566     # reclaim arr
 6567     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000010/imm32"    "F - test-convert-index-into-array-on-stack-with-literal/12")
 6568     #
 6569     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-on-stack-with-literal/13")
 6570     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-on-stack-with-literal/14")
 6571     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-on-stack-with-literal/15")
 6572     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-on-stack-with-literal/16")
 6573     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-on-stack-with-literal/17")
 6574     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-on-stack-with-literal/18")
 6575     # . epilogue
 6576     89/<- %esp 5/r32/ebp
 6577     5d/pop-to-ebp
 6578     c3/return
 6579 
 6580 test-convert-index-into-array-of-bytes-on-stack-with-literal:
 6581     # . prologue
 6582     55/push-ebp
 6583     89/<- %ebp 4/r32/esp
 6584     # setup
 6585     (clear-stream _test-input-stream)
 6586     (clear-stream $_test-input-buffered-file->buffer)
 6587     (clear-stream _test-output-stream)
 6588     (clear-stream $_test-output-buffered-file->buffer)
 6589     #
 6590     (write _test-input-stream "fn foo {\n")
 6591     (write _test-input-stream "  var arr: (array byte 3)\n")
 6592     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, 2\n")
 6593     (write _test-input-stream "}\n")
 6594     # convert
 6595     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6596     (flush _test-output-buffered-file)
 6597 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6603     # check output
 6604     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/0")
 6605     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/1")
 6606     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/2")
 6607     (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")
 6608     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/4")
 6609     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/5")
 6610     # var arr
 6611     (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")
 6612     (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")
 6613     # var x
 6614     (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")
 6615     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds 2 0x00000001 *(ebp+0xfffffff9) \"foo\" \"arr\")"  "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/9")
 6616     # x is at (ebp-7) + 4 + 2 = ebp-1
 6617     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp + 0xffffffff) 0x00000000/r32"  "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/10")
 6618     # reclaim x
 6619     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/11")
 6620     # reclaim arr
 6621     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000007/imm32"    "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/12")
 6622     #
 6623     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/13")
 6624     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/14")
 6625     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/15")
 6626     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/16")
 6627     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/17")
 6628     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/18")
 6629     # . epilogue
 6630     89/<- %esp 5/r32/ebp
 6631     5d/pop-to-ebp
 6632     c3/return
 6633 
 6634 test-convert-index-into-array-using-offset:
 6635     # . prologue
 6636     55/push-ebp
 6637     89/<- %ebp 4/r32/esp
 6638     # setup
 6639     (clear-stream _test-input-stream)
 6640     (clear-stream $_test-input-buffered-file->buffer)
 6641     (clear-stream _test-output-stream)
 6642     (clear-stream $_test-output-buffered-file->buffer)
 6643     #
 6644     (write _test-input-stream "fn foo {\n")
 6645     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
 6646     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
 6647     (write _test-input-stream "  var off/ecx: (offset int) <- compute-offset arr, idx\n")
 6648     (write _test-input-stream "  var x/eax: (addr int) <- index arr, off\n")
 6649     (write _test-input-stream "}\n")
 6650     # convert
 6651     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6652     (flush _test-output-buffered-file)
 6653 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6659     # check output
 6660     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-using-offset/0")
 6661     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-using-offset/1")
 6662     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-using-offset/2")
 6663     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-using-offset/3")
 6664     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-using-offset/4")
 6665     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-using-offset/5")
 6666     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-using-offset/6")
 6667     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array-using-offset/7")
 6668     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-using-offset/8")
 6669     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-index-into-array-using-offset/9")
 6670     (check-next-stream-line-equal _test-output-stream "    69/multiply %ecx 0x00000004/imm32 0x00000001/r32"  "F - test-convert-index-into-array-using-offset/10")
 6671     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds %ecx 1 *eax \"foo\" \"arr\")"  "F - test-convert-index-into-array-using-offset/11")
 6672     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx + 4) 0x00000000/r32"  "F - test-convert-index-into-array-using-offset/12")
 6673     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-using-offset/13")
 6674     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-using-offset/14")
 6675     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-using-offset/15")
 6676     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-using-offset/16")
 6677     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-using-offset/17")
 6678     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-using-offset/18")
 6679     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-using-offset/19")
 6680     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-using-offset/20")
 6681     # . epilogue
 6682     89/<- %esp 5/r32/ebp
 6683     5d/pop-to-ebp
 6684     c3/return
 6685 
 6686 test-convert-index-into-array-of-bytes-using-offset:
 6687     # . prologue
 6688     55/push-ebp
 6689     89/<- %ebp 4/r32/esp
 6690     # setup
 6691     (clear-stream _test-input-stream)
 6692     (clear-stream $_test-input-buffered-file->buffer)
 6693     (clear-stream _test-output-stream)
 6694     (clear-stream $_test-output-buffered-file->buffer)
 6695     #
 6696     (write _test-input-stream "fn foo {\n")
 6697     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
 6698     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
 6699     (write _test-input-stream "  var off/ecx: (offset byte) <- compute-offset arr, idx\n")
 6700     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, off\n")
 6701     (write _test-input-stream "}\n")
 6702     # convert
 6703     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6704     (flush _test-output-buffered-file)
 6705 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6711     # check output
 6712     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-using-offset/0")
 6713     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-using-offset/1")
 6714     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-using-offset/2")
 6715     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-of-bytes-using-offset/3")
 6716     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-using-offset/4")
 6717     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-using-offset/5")
 6718     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-of-bytes-using-offset/6")
 6719     (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")
 6720     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-of-bytes-using-offset/8")
 6721     (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")
 6722     (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")
 6723     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds %ecx 1 *eax \"foo\" \"arr\")"  "F - test-convert-index-into-array-of-bytes-using-offset/11")
 6724     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx + 4) 0x00000000/r32"  "F - test-convert-index-into-array-of-bytes-using-offset/12")
 6725     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-of-bytes-using-offset/13")
 6726     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes-using-offset/14")
 6727     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-using-offset/15")
 6728     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-using-offset/16")
 6729     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-using-offset/17")
 6730     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes-using-offset/18")
 6731     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes-using-offset/19")
 6732     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-using-offset/20")
 6733     # . epilogue
 6734     89/<- %esp 5/r32/ebp
 6735     5d/pop-to-ebp
 6736     c3/return
 6737 
 6738 test-convert-index-into-array-using-offset-on-stack:
 6739     # . prologue
 6740     55/push-ebp
 6741     89/<- %ebp 4/r32/esp
 6742     # setup
 6743     (clear-stream _test-input-stream)
 6744     (clear-stream $_test-input-buffered-file->buffer)
 6745     (clear-stream _test-output-stream)
 6746     (clear-stream $_test-output-buffered-file->buffer)
 6747     #
 6748     (write _test-input-stream "fn foo {\n")
 6749     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
 6750     (write _test-input-stream "  var idx: int\n")
 6751     (write _test-input-stream "  var off/ecx: (offset int) <- compute-offset arr, idx\n")
 6752     (write _test-input-stream "  var x/eax: (addr int) <- index arr, off\n")
 6753     (write _test-input-stream "}\n")
 6754     # convert
 6755     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6756     (flush _test-output-buffered-file)
 6757 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6763     # check output
 6764     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-using-offset-on-stack/0")
 6765     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-using-offset-on-stack/1")
 6766     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-using-offset-on-stack/2")
 6767     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-using-offset-on-stack/3")
 6768     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-using-offset-on-stack/4")
 6769     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-using-offset-on-stack/5")
 6770     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-using-offset-on-stack/6")
 6771     (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")
 6772     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"                         "F - test-convert-index-into-array-using-offset-on-stack/8")
 6773     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-using-offset-on-stack/9")
 6774     (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")
 6775     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds %ecx 1 *eax \"foo\" \"arr\")"  "F - test-convert-index-into-array-using-offset-on-stack/11")
 6776     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx + 4) 0x00000000/r32"  "F - test-convert-index-into-array-using-offset-on-stack/12")
 6777     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-using-offset-on-stack/13")
 6778     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"    "F - test-convert-index-into-array-using-offset-on-stack/14")
 6779     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-using-offset-on-stack/15")
 6780     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-using-offset-on-stack/16")
 6781     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-using-offset-on-stack/17")
 6782     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-using-offset-on-stack/18")
 6783     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-using-offset-on-stack/19")
 6784     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-using-offset-on-stack/20")
 6785     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-using-offset-on-stack/21")
 6786     # . epilogue
 6787     89/<- %esp 5/r32/ebp
 6788     5d/pop-to-ebp
 6789     c3/return
 6790 
 6791 test-convert-index-into-array-of-bytes-using-offset-on-stack:
 6792     # . prologue
 6793     55/push-ebp
 6794     89/<- %ebp 4/r32/esp
 6795     # setup
 6796     (clear-stream _test-input-stream)
 6797     (clear-stream $_test-input-buffered-file->buffer)
 6798     (clear-stream _test-output-stream)
 6799     (clear-stream $_test-output-buffered-file->buffer)
 6800     #
 6801     (write _test-input-stream "fn foo {\n")
 6802     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
 6803     (write _test-input-stream "  var idx: int\n")
 6804     (write _test-input-stream "  var off/ecx: (offset byte) <- compute-offset arr, idx\n")
 6805     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, off\n")
 6806     (write _test-input-stream "}\n")
 6807     # convert
 6808     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6809     (flush _test-output-buffered-file)
 6810 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6816     # check output
 6817     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/0")
 6818     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/1")
 6819     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/2")
 6820     (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")
 6821     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/4")
 6822     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/5")
 6823     (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")
 6824     (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")
 6825     (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")
 6826     (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")
 6827     (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")
 6828     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds %ecx 1 *eax \"foo\" \"arr\")"  "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/11")
 6829     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx + 4) 0x00000000/r32"  "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/12")
 6830     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/13")
 6831     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"    "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/14")
 6832     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/15")
 6833     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/16")
 6834     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/17")
 6835     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/18")
 6836     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/19")
 6837     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/20")
 6838     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/21")
 6839     # . epilogue
 6840     89/<- %esp 5/r32/ebp
 6841     5d/pop-to-ebp
 6842     c3/return
 6843 
 6844 test-convert-function-and-type-definition:
 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 "fn foo a: (addr t) {\n")
 6855     (write _test-input-stream "  var _a/eax: (addr t) <- copy a\n")
 6856     (write _test-input-stream "  var b/ecx: (addr int) <- get _a, x\n")
 6857     (write _test-input-stream "  var c/ecx: (addr int) <- get _a, y\n")
 6858     (write _test-input-stream "}\n")
 6859     (write _test-input-stream "type t {\n")
 6860     (write _test-input-stream "  x: int\n")
 6861     (write _test-input-stream "  y: int\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-function-and-type-definition/0")
 6874     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-and-type-definition/1")
 6875     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-and-type-definition/2")
 6876     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-and-type-definition/3")
 6877     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-and-type-definition/4")
 6878     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-and-type-definition/5")
 6879     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-and-type-definition/6")
 6880     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-function-and-type-definition/7")
 6881     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-and-type-definition/8")
 6882     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + 0x00000000) 0x00000001/r32"  "F - test-convert-function-and-type-definition/9")
 6883     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + 0x00000004) 0x00000001/r32"  "F - test-convert-function-and-type-definition/11")
 6884     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-and-type-definition/13")
 6885     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-function-and-type-definition/14")
 6886     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-and-type-definition/15")
 6887     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-and-type-definition/16")
 6888     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-and-type-definition/17")
 6889     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-and-type-definition/18")
 6890     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-and-type-definition/19")
 6891     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-and-type-definition/20")
 6892     # . epilogue
 6893     89/<- %esp 5/r32/ebp
 6894     5d/pop-to-ebp
 6895     c3/return
 6896 
 6897 test-type-definition-with-array:
 6898     # . prologue
 6899     55/push-ebp
 6900     89/<- %ebp 4/r32/esp
 6901     # setup
 6902     (clear-stream _test-input-stream)
 6903     (clear-stream $_test-input-buffered-file->buffer)
 6904     (clear-stream _test-output-stream)
 6905     (clear-stream $_test-output-buffered-file->buffer)
 6906     (clear-stream _test-error-stream)
 6907     (clear-stream $_test-error-buffered-file->buffer)
 6908     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6909     68/push 0/imm32
 6910     68/push 0/imm32
 6911     89/<- %edx 4/r32/esp
 6912     (tailor-exit-descriptor %edx 0x10)
 6913     #
 6914     (write _test-input-stream "type t {\n")
 6915     (write _test-input-stream "  a: (array int 3)\n")
 6916     (write _test-input-stream "}\n")
 6917     # convert
 6918     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6919     # registers except esp clobbered at this point
 6920     # restore ed
 6921     89/<- %edx 4/r32/esp
 6922     (flush _test-output-buffered-file)
 6923     (flush _test-error-buffered-file)
 6924 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 6930     # check output
 6931     (check-stream-equal _test-output-stream  ""  "F - test-type-definition-with-array: output should be empty")
 6932     (check-next-stream-line-equal _test-error-stream  "type t: 'array' elements not allowed for now"  "F - test-type-definition-with-array: error message")
 6933     # check that stop(1) was called
 6934     (check-ints-equal *(edx+4) 2 "F - test-type-definition-with-array: exit status")
 6935     # don't restore from ebp
 6936     81 0/subop/add %esp 8/imm32
 6937     # . epilogue
 6938     5d/pop-to-ebp
 6939     c3/return
 6940 
 6941 test-type-definition-with-addr:
 6942     # . prologue
 6943     55/push-ebp
 6944     89/<- %ebp 4/r32/esp
 6945     # setup
 6946     (clear-stream _test-input-stream)
 6947     (clear-stream $_test-input-buffered-file->buffer)
 6948     (clear-stream _test-output-stream)
 6949     (clear-stream $_test-output-buffered-file->buffer)
 6950     (clear-stream _test-error-stream)
 6951     (clear-stream $_test-error-buffered-file->buffer)
 6952     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6953     68/push 0/imm32
 6954     68/push 0/imm32
 6955     89/<- %edx 4/r32/esp
 6956     (tailor-exit-descriptor %edx 0x10)
 6957     #
 6958     (write _test-input-stream "type t {\n")
 6959     (write _test-input-stream "  a: (addr int)\n")
 6960     (write _test-input-stream "}\n")
 6961     # convert
 6962     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6963     # registers except esp clobbered at this point
 6964     # restore ed
 6965     89/<- %edx 4/r32/esp
 6966     (flush _test-output-buffered-file)
 6967     (flush _test-error-buffered-file)
 6968 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 6974     # check output
 6975     (check-stream-equal _test-output-stream  ""  "F - test-type-definition-with-addr: output should be empty")
 6976     (check-next-stream-line-equal _test-error-stream  "type t: 'addr' elements not allowed"  "F - test-type-definition-with-addr: error message")
 6977     # check that stop(1) was called
 6978     (check-ints-equal *(edx+4) 2 "F - test-type-definition-with-addr: exit status")
 6979     # don't restore from ebp
 6980     81 0/subop/add %esp 8/imm32
 6981     # . epilogue
 6982     5d/pop-to-ebp
 6983     c3/return
 6984 
 6985 test-convert-function-with-local-var-with-user-defined-type:
 6986     # . prologue
 6987     55/push-ebp
 6988     89/<- %ebp 4/r32/esp
 6989     # setup
 6990     (clear-stream _test-input-stream)
 6991     (clear-stream $_test-input-buffered-file->buffer)
 6992     (clear-stream _test-output-stream)
 6993     (clear-stream $_test-output-buffered-file->buffer)
 6994     #
 6995     (write _test-input-stream "fn foo {\n")
 6996     (write _test-input-stream "  var a: t\n")
 6997     (write _test-input-stream "}\n")
 6998     (write _test-input-stream "type t {\n")
 6999     (write _test-input-stream "  x: int\n")
 7000     (write _test-input-stream "  y: int\n")
 7001     (write _test-input-stream "}\n")
 7002     # convert
 7003     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7004     (flush _test-output-buffered-file)
 7005 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 7011     # check output
 7012     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-with-user-defined-type/0")
 7013     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-with-user-defined-type/1")
 7014     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-with-user-defined-type/2")
 7015     (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")
 7016     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-with-user-defined-type/4")
 7017     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-with-user-defined-type/5")
 7018     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-with-user-defined-type/6")
 7019     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-with-user-defined-type/7")
 7020     (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")
 7021     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-with-user-defined-type/9")
 7022     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-with-user-defined-type/10")
 7023     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-with-user-defined-type/11")
 7024     (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")
 7025     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-with-user-defined-type/13")
 7026     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-with-user-defined-type/14")
 7027     # . epilogue
 7028     89/<- %esp 5/r32/ebp
 7029     5d/pop-to-ebp
 7030     c3/return
 7031 
 7032 test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type:
 7033     # . prologue
 7034     55/push-ebp
 7035     89/<- %ebp 4/r32/esp
 7036     # setup
 7037     (clear-stream _test-input-stream)
 7038     (clear-stream $_test-input-buffered-file->buffer)
 7039     (clear-stream _test-output-stream)
 7040     (clear-stream $_test-output-buffered-file->buffer)
 7041     #
 7042     (write _test-input-stream "fn foo {\n")
 7043     (write _test-input-stream "  var a: t\n")
 7044     (write _test-input-stream "}\n")
 7045     (write _test-input-stream "type t {\n")
 7046     (write _test-input-stream "  x: s\n")
 7047     (write _test-input-stream "}\n")
 7048     (write _test-input-stream "type s {\n")
 7049     (write _test-input-stream "  z: int\n")
 7050     (write _test-input-stream "}\n")
 7051     # convert
 7052     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7053     (flush _test-output-buffered-file)
 7054 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 7060     # check output
 7061     (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")
 7062     (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")
 7063     (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")
 7064     (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")
 7065     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/4")
 7066     (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")
 7067     (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")
 7068     (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")
 7069     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/9")
 7070     (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")
 7071     (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")
 7072     (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")
 7073     (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")
 7074     (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")
 7075     # . epilogue
 7076     89/<- %esp 5/r32/ebp
 7077     5d/pop-to-ebp
 7078     c3/return
 7079 
 7080 test-convert-function-call-with-arg-of-user-defined-type:
 7081     # . prologue
 7082     55/push-ebp
 7083     89/<- %ebp 4/r32/esp
 7084     # setup
 7085     (clear-stream _test-input-stream)
 7086     (clear-stream $_test-input-buffered-file->buffer)
 7087     (clear-stream _test-output-stream)
 7088     (clear-stream $_test-output-buffered-file->buffer)
 7089     #
 7090     (write _test-input-stream "fn f {\n")
 7091     (write _test-input-stream "  var a: t\n")
 7092     (write _test-input-stream "  foo a\n")
 7093     (write _test-input-stream "}\n")
 7094     (write _test-input-stream "fn foo x: t {\n")
 7095     (write _test-input-stream "}\n")
 7096     (write _test-input-stream "type t {\n")
 7097     (write _test-input-stream "  x: int\n")
 7098     (write _test-input-stream "  y: int\n")
 7099     (write _test-input-stream "}\n")
 7100     # convert
 7101     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7102     (flush _test-output-buffered-file)
 7103 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 7109     # check output
 7110     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-arg-of-user-defined-type/0")
 7111     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/1")
 7112     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/2")
 7113     (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")
 7114     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type/4")
 7115     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"     "F - test-convert-function-call-with-arg-of-user-defined-type/5")
 7116     # var a: t
 7117     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-call-with-arg-of-user-defined-type/6")
 7118     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-call-with-arg-of-user-defined-type/7")
 7119     # foo a
 7120     (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")
 7121     #
 7122     (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")
 7123     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type/10")
 7124     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"    "F - test-convert-function-call-with-arg-of-user-defined-type/11")
 7125     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/12")
 7126     (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")
 7127     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/14")
 7128     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/15")
 7129     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call-with-arg-of-user-defined-type/16")
 7130     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/17")
 7131     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/18")
 7132     (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")
 7133     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/20")
 7134     (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")
 7135     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/22")
 7136     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/23")
 7137     # . epilogue
 7138     89/<- %esp 5/r32/ebp
 7139     5d/pop-to-ebp
 7140     c3/return
 7141 
 7142 test-convert-function-call-with-arg-of-user-defined-type-register-indirect:
 7143     # . prologue
 7144     55/push-ebp
 7145     89/<- %ebp 4/r32/esp
 7146     # setup
 7147     (clear-stream _test-input-stream)
 7148     (clear-stream $_test-input-buffered-file->buffer)
 7149     (clear-stream _test-output-stream)
 7150     (clear-stream $_test-output-buffered-file->buffer)
 7151     #
 7152     (write _test-input-stream "fn f {\n")
 7153     (write _test-input-stream "  var a/eax: (addr t) <- copy 0\n")
 7154     (write _test-input-stream "  foo *a\n")
 7155     (write _test-input-stream "}\n")
 7156     (write _test-input-stream "fn foo x: t {\n")
 7157     (write _test-input-stream "}\n")
 7158     (write _test-input-stream "type t {\n")
 7159     (write _test-input-stream "  x: int\n")
 7160     (write _test-input-stream "  y: int\n")
 7161     (write _test-input-stream "}\n")
 7162     # convert
 7163     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7164     (flush _test-output-buffered-file)
 7165 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 7171     # check output
 7172     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-arg-of-user-defined-type/0")
 7173     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/1")
 7174     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/2")
 7175     (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")
 7176     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type/4")
 7177     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"     "F - test-convert-function-call-with-arg-of-user-defined-type/5")
 7178     # var a
 7179     (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")
 7180     (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")
 7181     # foo a
 7182     (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")
 7183     #
 7184     (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")
 7185     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type/10")
 7186     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"    "F - test-convert-function-call-with-arg-of-user-defined-type/11")
 7187     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/12")
 7188     (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")
 7189     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/14")
 7190     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/15")
 7191     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call-with-arg-of-user-defined-type/16")
 7192     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/17")
 7193     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/18")
 7194     (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")
 7195     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/20")
 7196     (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")
 7197     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/22")
 7198     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/23")
 7199     # . epilogue
 7200     89/<- %esp 5/r32/ebp
 7201     5d/pop-to-ebp
 7202     c3/return
 7203 
 7204 # we don't have special support for call-by-reference; just explicitly create
 7205 # a new variable with the address of the arg
 7206 test-convert-function-call-with-arg-of-user-defined-type-by-reference:
 7207     # . prologue
 7208     55/push-ebp
 7209     89/<- %ebp 4/r32/esp
 7210     # setup
 7211     (clear-stream _test-input-stream)
 7212     (clear-stream $_test-input-buffered-file->buffer)
 7213     (clear-stream _test-output-stream)
 7214     (clear-stream $_test-output-buffered-file->buffer)
 7215     #
 7216     (write _test-input-stream "fn f {\n")
 7217     (write _test-input-stream "  var a: t\n")
 7218     (write _test-input-stream "  var b/eax: (addr t) <- address a\n")
 7219     (write _test-input-stream "  foo b\n")
 7220     (write _test-input-stream "}\n")
 7221     (write _test-input-stream "fn foo x: (addr t) {\n")
 7222     (write _test-input-stream "  var x/ecx: (addr t) <- copy x\n")
 7223     (write _test-input-stream "}\n")
 7224     (write _test-input-stream "type t {\n")
 7225     (write _test-input-stream "  x: int\n")
 7226     (write _test-input-stream "  y: int\n")
 7227     (write _test-input-stream "}\n")
 7228     # convert
 7229     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7230     (flush _test-output-buffered-file)
 7231 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 7237     # check output
 7238     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/0")
 7239     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/1")
 7240     (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")
 7241     (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")
 7242     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/4")
 7243     (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")
 7244     # var a: t
 7245     (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")
 7246     (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")
 7247     # var b/eax: (addr t)
 7248     (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")
 7249     (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")
 7250     # foo a
 7251     (check-next-stream-line-equal _test-output-stream "    (foo %eax)"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/10")
 7252     #
 7253     (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")
 7254     (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")
 7255     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/13")
 7256     (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")
 7257     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/15")
 7258     (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")
 7259     (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")
 7260     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/18")
 7261     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/19")
 7262     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/20")
 7263     (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")
 7264     (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")
 7265     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/23")
 7266     (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")
 7267     (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")
 7268     (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")
 7269     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/27")
 7270     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/28")
 7271     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/29")
 7272     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/30")
 7273     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/31")
 7274     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/32")
 7275     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/33")
 7276     # . epilogue
 7277     89/<- %esp 5/r32/ebp
 7278     5d/pop-to-ebp
 7279     c3/return
 7280 
 7281 test-convert-get-on-local-variable:
 7282     # . prologue
 7283     55/push-ebp
 7284     89/<- %ebp 4/r32/esp
 7285     # setup
 7286     (clear-stream _test-input-stream)
 7287     (clear-stream $_test-input-buffered-file->buffer)
 7288     (clear-stream _test-output-stream)
 7289     (clear-stream $_test-output-buffered-file->buffer)
 7290     #
 7291     (write _test-input-stream "fn foo {\n")
 7292     (write _test-input-stream "  var a: t\n")
 7293     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 7294     (write _test-input-stream "}\n")
 7295     (write _test-input-stream "type t {\n")
 7296     (write _test-input-stream "  x: int\n")
 7297     (write _test-input-stream "  y: int\n")
 7298     (write _test-input-stream "}\n")
 7299     # convert
 7300     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7301     (flush _test-output-buffered-file)
 7302 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 7308     # check output
 7309     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-get-on-local-variable/0")
 7310     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-get-on-local-variable/1")
 7311     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-get-on-local-variable/2")
 7312     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-get-on-local-variable/3")
 7313     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-get-on-local-variable/4")
 7314     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-get-on-local-variable/5")
 7315     # var a
 7316     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-get-on-local-variable/6")
 7317     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-get-on-local-variable/7")
 7318     # var c
 7319     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-get-on-local-variable/8")
 7320     # get
 7321     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp+0xfffffffc) 0x00000001/r32"  "F - test-convert-get-on-local-variable/9")
 7322     # reclaim c
 7323     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-get-on-local-variable/10")
 7324     # reclaim a
 7325     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000008/imm32"  "F - test-convert-get-on-local-variable/11")
 7326     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-get-on-local-variable/12")
 7327     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-get-on-local-variable/13")
 7328     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-get-on-local-variable/14")
 7329     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-get-on-local-variable/15")
 7330     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-get-on-local-variable/16")
 7331     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-get-on-local-variable/17")
 7332     # . epilogue
 7333     89/<- %esp 5/r32/ebp
 7334     5d/pop-to-ebp
 7335     c3/return
 7336 
 7337 test-convert-get-on-function-argument:
 7338     # . prologue
 7339     55/push-ebp
 7340     89/<- %ebp 4/r32/esp
 7341     # setup
 7342     (clear-stream _test-input-stream)
 7343     (clear-stream $_test-input-buffered-file->buffer)
 7344     (clear-stream _test-output-stream)
 7345     (clear-stream $_test-output-buffered-file->buffer)
 7346     #
 7347     (write _test-input-stream "fn foo a: t {\n")
 7348     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 7349     (write _test-input-stream "}\n")
 7350     (write _test-input-stream "type t {\n")
 7351     (write _test-input-stream "  x: int\n")
 7352     (write _test-input-stream "  y: int\n")
 7353     (write _test-input-stream "}\n")
 7354     # convert
 7355     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7356     (flush _test-output-buffered-file)
 7357 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 7363     # check output
 7364     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-get-on-function-argument/0")
 7365     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-get-on-function-argument/1")
 7366     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-get-on-function-argument/2")
 7367     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-get-on-function-argument/3")
 7368     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-get-on-function-argument/4")
 7369     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-get-on-function-argument/5")
 7370     # var c
 7371     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-get-on-function-argument/6")
 7372     # get
 7373     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp+0x0000000c) 0x00000001/r32"  "F - test-convert-get-on-function-argument/7")
 7374     # reclaim c
 7375     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-get-on-function-argument/8")
 7376     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-get-on-function-argument/9")
 7377     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-get-on-function-argument/10")
 7378     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-get-on-function-argument/11")
 7379     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-get-on-function-argument/12")
 7380     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-get-on-function-argument/13")
 7381     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-get-on-function-argument/14")
 7382     # . epilogue
 7383     89/<- %esp 5/r32/ebp
 7384     5d/pop-to-ebp
 7385     c3/return
 7386 
 7387 test-convert-get-on-function-argument-with-known-type:
 7388     # . prologue
 7389     55/push-ebp
 7390     89/<- %ebp 4/r32/esp
 7391     # setup
 7392     (clear-stream _test-input-stream)
 7393     (clear-stream $_test-input-buffered-file->buffer)
 7394     (clear-stream _test-output-stream)
 7395     (clear-stream $_test-output-buffered-file->buffer)
 7396     #
 7397     (write _test-input-stream "type t {\n")
 7398     (write _test-input-stream "  x: int\n")
 7399     (write _test-input-stream "  y: int\n")
 7400     (write _test-input-stream "}\n")
 7401     (write _test-input-stream "fn foo a: t {\n")
 7402     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 7403     (write _test-input-stream "}\n")
 7404     # convert
 7405     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7406     (flush _test-output-buffered-file)
 7407 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 7413     # check output
 7414     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-get-on-function-argument-with-known-type/0")
 7415     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-get-on-function-argument-with-known-type/1")
 7416     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-get-on-function-argument-with-known-type/2")
 7417     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-get-on-function-argument-with-known-type/3")
 7418     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-get-on-function-argument-with-known-type/4")
 7419     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-get-on-function-argument-with-known-type/5")
 7420     # var c
 7421     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-get-on-function-argument-with-known-type/6")
 7422     # get
 7423     (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")
 7424     # reclaim c
 7425     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-get-on-function-argument-with-known-type/8")
 7426     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-get-on-function-argument-with-known-type/9")
 7427     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-get-on-function-argument-with-known-type/10")
 7428     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-get-on-function-argument-with-known-type/11")
 7429     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-get-on-function-argument-with-known-type/12")
 7430     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-get-on-function-argument-with-known-type/13")
 7431     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-get-on-function-argument-with-known-type/14")
 7432     # . epilogue
 7433     89/<- %esp 5/r32/ebp
 7434     5d/pop-to-ebp
 7435     c3/return
 7436 
 7437 test-add-with-too-many-inouts:
 7438     # . prologue
 7439     55/push-ebp
 7440     89/<- %ebp 4/r32/esp
 7441     # setup
 7442     (clear-stream _test-input-stream)
 7443     (clear-stream $_test-input-buffered-file->buffer)
 7444     (clear-stream _test-output-stream)
 7445     (clear-stream $_test-output-buffered-file->buffer)
 7446     (clear-stream _test-error-stream)
 7447     (clear-stream $_test-error-buffered-file->buffer)
 7448     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7449     68/push 0/imm32
 7450     68/push 0/imm32
 7451     89/<- %edx 4/r32/esp
 7452     (tailor-exit-descriptor %edx 0x10)
 7453     #
 7454     (write _test-input-stream "fn foo {\n")
 7455     (write _test-input-stream "  var a: int\n")
 7456     (write _test-input-stream "  var b/ecx: int <- add a, 0\n")
 7457     (write _test-input-stream "}\n")
 7458     # convert
 7459     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7460     # registers except esp clobbered at this point
 7461     # restore ed
 7462     89/<- %edx 4/r32/esp
 7463     (flush _test-output-buffered-file)
 7464     (flush _test-error-buffered-file)
 7465 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7471     # check output
 7472     (check-stream-equal _test-output-stream  ""  "F - test-add-with-too-many-inouts: output should be empty")
 7473     (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")
 7474     # check that stop(1) was called
 7475     (check-ints-equal *(edx+4) 2 "F - test-add-with-too-many-inouts: exit status")
 7476     # don't restore from ebp
 7477     81 0/subop/add %esp 8/imm32
 7478     # . epilogue
 7479     5d/pop-to-ebp
 7480     c3/return
 7481 
 7482 test-add-with-too-many-inouts-2:
 7483     # . prologue
 7484     55/push-ebp
 7485     89/<- %ebp 4/r32/esp
 7486     # setup
 7487     (clear-stream _test-input-stream)
 7488     (clear-stream $_test-input-buffered-file->buffer)
 7489     (clear-stream _test-output-stream)
 7490     (clear-stream $_test-output-buffered-file->buffer)
 7491     (clear-stream _test-error-stream)
 7492     (clear-stream $_test-error-buffered-file->buffer)
 7493     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7494     68/push 0/imm32
 7495     68/push 0/imm32
 7496     89/<- %edx 4/r32/esp
 7497     (tailor-exit-descriptor %edx 0x10)
 7498     #
 7499     (write _test-input-stream "fn foo {\n")
 7500     (write _test-input-stream "  var a: int\n")
 7501     (write _test-input-stream "  add-to a, 0, 1\n")
 7502     (write _test-input-stream "}\n")
 7503     # convert
 7504     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7505     # registers except esp clobbered at this point
 7506     # restore ed
 7507     89/<- %edx 4/r32/esp
 7508     (flush _test-output-buffered-file)
 7509     (flush _test-error-buffered-file)
 7510 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7516     # check output
 7517     (check-stream-equal _test-output-stream  ""  "F - test-add-with-too-many-inouts-2: output should be empty")
 7518     (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")
 7519     # check that stop(1) was called
 7520     (check-ints-equal *(edx+4) 2 "F - test-add-with-too-many-inouts-2: exit status")
 7521     # don't restore from ebp
 7522     81 0/subop/add %esp 8/imm32
 7523     # . epilogue
 7524     5d/pop-to-ebp
 7525     c3/return
 7526 
 7527 test-add-with-too-many-outputs:
 7528     # . prologue
 7529     55/push-ebp
 7530     89/<- %ebp 4/r32/esp
 7531     # setup
 7532     (clear-stream _test-input-stream)
 7533     (clear-stream $_test-input-buffered-file->buffer)
 7534     (clear-stream _test-output-stream)
 7535     (clear-stream $_test-output-buffered-file->buffer)
 7536     (clear-stream _test-error-stream)
 7537     (clear-stream $_test-error-buffered-file->buffer)
 7538     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7539     68/push 0/imm32
 7540     68/push 0/imm32
 7541     89/<- %edx 4/r32/esp
 7542     (tailor-exit-descriptor %edx 0x10)
 7543     #
 7544     (write _test-input-stream "fn foo {\n")
 7545     (write _test-input-stream "  var a/eax: int <- copy 0\n")
 7546     (write _test-input-stream "  var b/ebx: int <- copy 0\n")
 7547     (write _test-input-stream "  var c/ecx: int <- copy 0\n")
 7548     (write _test-input-stream "  c, b <- add a\n")
 7549     (write _test-input-stream "}\n")
 7550     # convert
 7551     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7552     # registers except esp clobbered at this point
 7553     # restore ed
 7554     89/<- %edx 4/r32/esp
 7555     (flush _test-output-buffered-file)
 7556     (flush _test-error-buffered-file)
 7557 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7563     # check output
 7564     (check-stream-equal _test-output-stream  ""  "F - test-add-with-too-many-outputs: output should be empty")
 7565     (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")
 7566     # check that stop(1) was called
 7567     (check-ints-equal *(edx+4) 2 "F - test-add-with-too-many-outputs: exit status")
 7568     # don't restore from ebp
 7569     81 0/subop/add %esp 8/imm32
 7570     # . epilogue
 7571     5d/pop-to-ebp
 7572     c3/return
 7573 
 7574 test-add-with-non-number:
 7575     # . prologue
 7576     55/push-ebp
 7577     89/<- %ebp 4/r32/esp
 7578     # setup
 7579     (clear-stream _test-input-stream)
 7580     (clear-stream $_test-input-buffered-file->buffer)
 7581     (clear-stream _test-output-stream)
 7582     (clear-stream $_test-output-buffered-file->buffer)
 7583     (clear-stream _test-error-stream)
 7584     (clear-stream $_test-error-buffered-file->buffer)
 7585     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7586     68/push 0/imm32
 7587     68/push 0/imm32
 7588     89/<- %edx 4/r32/esp
 7589     (tailor-exit-descriptor %edx 0x10)
 7590     #
 7591     (write _test-input-stream "fn foo {\n")
 7592     (write _test-input-stream "  var a: int\n")
 7593     (write _test-input-stream "  var b/ecx: (addr int) <- add a\n")
 7594     (write _test-input-stream "}\n")
 7595     # convert
 7596     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7597     # registers except esp clobbered at this point
 7598     # restore ed
 7599     89/<- %edx 4/r32/esp
 7600     (flush _test-output-buffered-file)
 7601     (flush _test-error-buffered-file)
 7602 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7608     # check output
 7609     (check-stream-equal _test-output-stream  ""  "F - test-add-with-non-number: output should be empty")
 7610     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt add: 'b' must be a non-addr non-offset scalar"  "F - test-add-with-non-number: error message")
 7611     # check that stop(1) was called
 7612     (check-ints-equal *(edx+4) 2 "F - test-add-with-non-number: exit status")
 7613     # don't restore from ebp
 7614     81 0/subop/add %esp 8/imm32
 7615     # . epilogue
 7616     5d/pop-to-ebp
 7617     c3/return
 7618 
 7619 test-add-with-addr-dereferenced:
 7620     # . prologue
 7621     55/push-ebp
 7622     89/<- %ebp 4/r32/esp
 7623     # setup
 7624     (clear-stream _test-input-stream)
 7625     (clear-stream $_test-input-buffered-file->buffer)
 7626     (clear-stream _test-output-stream)
 7627     (clear-stream $_test-output-buffered-file->buffer)
 7628     #
 7629     (write _test-input-stream "fn foo {\n")
 7630     (write _test-input-stream "  var a/eax: (addr int) <- copy 0\n")
 7631     (write _test-input-stream "  add-to *a, 1\n")
 7632     (write _test-input-stream "}\n")
 7633     # convert
 7634     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7635     (flush _test-output-buffered-file)
 7636     # no error
 7637     # . epilogue
 7638     89/<- %esp 5/r32/ebp
 7639     5d/pop-to-ebp
 7640     c3/return
 7641 
 7642 test-copy-with-no-inout:
 7643     # . prologue
 7644     55/push-ebp
 7645     89/<- %ebp 4/r32/esp
 7646     # setup
 7647     (clear-stream _test-input-stream)
 7648     (clear-stream $_test-input-buffered-file->buffer)
 7649     (clear-stream _test-output-stream)
 7650     (clear-stream $_test-output-buffered-file->buffer)
 7651     (clear-stream _test-error-stream)
 7652     (clear-stream $_test-error-buffered-file->buffer)
 7653     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7654     68/push 0/imm32
 7655     68/push 0/imm32
 7656     89/<- %edx 4/r32/esp
 7657     (tailor-exit-descriptor %edx 0x10)
 7658     #
 7659     (write _test-input-stream "fn foo {\n")
 7660     (write _test-input-stream "  var x/eax: boolean <- copy\n")
 7661     (write _test-input-stream "}\n")
 7662     # convert
 7663     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7664     # registers except esp clobbered at this point
 7665     # restore ed
 7666     89/<- %edx 4/r32/esp
 7667     (flush _test-output-buffered-file)
 7668     (flush _test-error-buffered-file)
 7669 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7675     # check output
 7676     (check-stream-equal _test-output-stream  ""  "F - test-copy-with-no-inout: output should be empty")
 7677     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy' expects an inout"  "F - test-copy-with-no-inout: error message")
 7678     # check that stop(1) was called
 7679     (check-ints-equal *(edx+4) 2 "F - test-copy-with-no-inout: exit status")
 7680     # don't restore from ebp
 7681     81 0/subop/add %esp 8/imm32
 7682     # . epilogue
 7683     5d/pop-to-ebp
 7684     c3/return
 7685 
 7686 test-copy-with-multiple-inouts:
 7687     # . prologue
 7688     55/push-ebp
 7689     89/<- %ebp 4/r32/esp
 7690     # setup
 7691     (clear-stream _test-input-stream)
 7692     (clear-stream $_test-input-buffered-file->buffer)
 7693     (clear-stream _test-output-stream)
 7694     (clear-stream $_test-output-buffered-file->buffer)
 7695     (clear-stream _test-error-stream)
 7696     (clear-stream $_test-error-buffered-file->buffer)
 7697     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7698     68/push 0/imm32
 7699     68/push 0/imm32
 7700     89/<- %edx 4/r32/esp
 7701     (tailor-exit-descriptor %edx 0x10)
 7702     #
 7703     (write _test-input-stream "fn foo {\n")
 7704     (write _test-input-stream "  var x/eax: boolean <- copy 0, 0\n")
 7705     (write _test-input-stream "}\n")
 7706     # convert
 7707     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7708     # registers except esp clobbered at this point
 7709     # restore ed
 7710     89/<- %edx 4/r32/esp
 7711     (flush _test-output-buffered-file)
 7712     (flush _test-error-buffered-file)
 7713 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7719     # check output
 7720     (check-stream-equal _test-output-stream  ""  "F - test-copy-with-multiple-inouts: output should be empty")
 7721     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy' must have just one inout"  "F - test-copy-with-multiple-inouts: error message")
 7722     # check that stop(1) was called
 7723     (check-ints-equal *(edx+4) 2 "F - test-copy-with-multiple-inouts: exit status")
 7724     # don't restore from ebp
 7725     81 0/subop/add %esp 8/imm32
 7726     # . epilogue
 7727     5d/pop-to-ebp
 7728     c3/return
 7729 
 7730 test-copy-with-no-output:
 7731     # . prologue
 7732     55/push-ebp
 7733     89/<- %ebp 4/r32/esp
 7734     # setup
 7735     (clear-stream _test-input-stream)
 7736     (clear-stream $_test-input-buffered-file->buffer)
 7737     (clear-stream _test-output-stream)
 7738     (clear-stream $_test-output-buffered-file->buffer)
 7739     (clear-stream _test-error-stream)
 7740     (clear-stream $_test-error-buffered-file->buffer)
 7741     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7742     68/push 0/imm32
 7743     68/push 0/imm32
 7744     89/<- %edx 4/r32/esp
 7745     (tailor-exit-descriptor %edx 0x10)
 7746     #
 7747     (write _test-input-stream "fn foo {\n")
 7748     (write _test-input-stream "  copy 0\n")
 7749     (write _test-input-stream "}\n")
 7750     # convert
 7751     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7752     # registers except esp clobbered at this point
 7753     # restore ed
 7754     89/<- %edx 4/r32/esp
 7755     (flush _test-output-buffered-file)
 7756     (flush _test-error-buffered-file)
 7757 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7763     # check output
 7764     (check-stream-equal _test-output-stream  ""  "F - test-copy-with-no-output: output should be empty")
 7765     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy' expects an output"  "F - test-copy-with-no-output: error message")
 7766     # check that stop(1) was called
 7767     (check-ints-equal *(edx+4) 2 "F - test-copy-with-no-output: exit status")
 7768     # don't restore from ebp
 7769     81 0/subop/add %esp 8/imm32
 7770     # . epilogue
 7771     5d/pop-to-ebp
 7772     c3/return
 7773 
 7774 test-copy-with-multiple-outputs:
 7775     # . prologue
 7776     55/push-ebp
 7777     89/<- %ebp 4/r32/esp
 7778     # setup
 7779     (clear-stream _test-input-stream)
 7780     (clear-stream $_test-input-buffered-file->buffer)
 7781     (clear-stream _test-output-stream)
 7782     (clear-stream $_test-output-buffered-file->buffer)
 7783     (clear-stream _test-error-stream)
 7784     (clear-stream $_test-error-buffered-file->buffer)
 7785     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7786     68/push 0/imm32
 7787     68/push 0/imm32
 7788     89/<- %edx 4/r32/esp
 7789     (tailor-exit-descriptor %edx 0x10)
 7790     #
 7791     (write _test-input-stream "fn foo {\n")
 7792     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
 7793     (write _test-input-stream "  var y/ecx: boolean <- copy 0\n")
 7794     (write _test-input-stream "  x, y <- copy 0\n")
 7795     (write _test-input-stream "}\n")
 7796     # convert
 7797     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7798     # registers except esp clobbered at this point
 7799     # restore ed
 7800     89/<- %edx 4/r32/esp
 7801     (flush _test-output-buffered-file)
 7802     (flush _test-error-buffered-file)
 7803 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7809     # check output
 7810     (check-stream-equal _test-output-stream  ""  "F - test-copy-with-multiple-outputs: output should be empty")
 7811     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy' must have just one output"  "F - test-copy-with-multiple-outputs: error message")
 7812     # check that stop(1) was called
 7813     (check-ints-equal *(edx+4) 2 "F - test-copy-with-multiple-outputs: exit status")
 7814     # don't restore from ebp
 7815     81 0/subop/add %esp 8/imm32
 7816     # . epilogue
 7817     5d/pop-to-ebp
 7818     c3/return
 7819 
 7820 test-copy-invalid-value-to-address:
 7821     # . prologue
 7822     55/push-ebp
 7823     89/<- %ebp 4/r32/esp
 7824     # setup
 7825     (clear-stream _test-input-stream)
 7826     (clear-stream $_test-input-buffered-file->buffer)
 7827     (clear-stream _test-output-stream)
 7828     (clear-stream $_test-output-buffered-file->buffer)
 7829     (clear-stream _test-error-stream)
 7830     (clear-stream $_test-error-buffered-file->buffer)
 7831     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7832     68/push 0/imm32
 7833     68/push 0/imm32
 7834     89/<- %edx 4/r32/esp
 7835     (tailor-exit-descriptor %edx 0x10)
 7836     #
 7837     (write _test-input-stream "fn foo {\n")
 7838     (write _test-input-stream "  var x/eax: int <- copy 0\n")
 7839     (write _test-input-stream "  var y/ecx: (addr int) <- copy x\n")
 7840     (write _test-input-stream "}\n")
 7841     # convert
 7842     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7843     # registers except esp clobbered at this point
 7844     # restore ed
 7845     89/<- %edx 4/r32/esp
 7846     (flush _test-output-buffered-file)
 7847     (flush _test-error-buffered-file)
 7848 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7854     # check output
 7855     (check-stream-equal _test-output-stream  ""  "F - test-copy-invalid-value-to-address: output should be empty")
 7856     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy: 'y' must be a non-addr non-offset scalar"  "F - test-copy-invalid-value-to-address: error message")
 7857     # check that stop(1) was called
 7858     (check-ints-equal *(edx+4) 2 "F - test-copy-invalid-value-to-address: exit status")
 7859     # don't restore from ebp
 7860     81 0/subop/add %esp 8/imm32
 7861     # . epilogue
 7862     5d/pop-to-ebp
 7863     c3/return
 7864 
 7865 test-copy-null-value-to-address:
 7866     # . prologue
 7867     55/push-ebp
 7868     89/<- %ebp 4/r32/esp
 7869     # setup
 7870     (clear-stream _test-input-stream)
 7871     (clear-stream $_test-input-buffered-file->buffer)
 7872     (clear-stream _test-output-stream)
 7873     (clear-stream $_test-output-buffered-file->buffer)
 7874     #
 7875     (write _test-input-stream "fn foo {\n")
 7876     (write _test-input-stream "  var y/ecx: (addr int) <- copy 0\n")
 7877     (write _test-input-stream "}\n")
 7878     # convert
 7879     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7880     (flush _test-output-buffered-file)
 7881     # no errors
 7882     # . epilogue
 7883     89/<- %esp 5/r32/ebp
 7884     5d/pop-to-ebp
 7885     c3/return
 7886 
 7887 test-copy-invalid-value-to-offset:
 7888     # . prologue
 7889     55/push-ebp
 7890     89/<- %ebp 4/r32/esp
 7891     # setup
 7892     (clear-stream _test-input-stream)
 7893     (clear-stream $_test-input-buffered-file->buffer)
 7894     (clear-stream _test-output-stream)
 7895     (clear-stream $_test-output-buffered-file->buffer)
 7896     (clear-stream _test-error-stream)
 7897     (clear-stream $_test-error-buffered-file->buffer)
 7898     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7899     68/push 0/imm32
 7900     68/push 0/imm32
 7901     89/<- %edx 4/r32/esp
 7902     (tailor-exit-descriptor %edx 0x10)
 7903     #
 7904     (write _test-input-stream "fn foo {\n")
 7905     (write _test-input-stream "  var x/eax: int <- copy 0\n")
 7906     (write _test-input-stream "  var y/ecx: (offset int) <- copy x\n")
 7907     (write _test-input-stream "}\n")
 7908     # convert
 7909     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7910     # registers except esp clobbered at this point
 7911     # restore ed
 7912     89/<- %edx 4/r32/esp
 7913     (flush _test-output-buffered-file)
 7914     (flush _test-error-buffered-file)
 7915 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7921     # check output
 7922     (check-stream-equal _test-output-stream  ""  "F - test-copy-invalid-value-to-address: output should be empty")
 7923     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy: 'y' must be a non-addr non-offset scalar"  "F - test-copy-invalid-value-to-address: error message")
 7924     # check that stop(1) was called
 7925     (check-ints-equal *(edx+4) 2 "F - test-copy-invalid-value-to-offset: exit status")
 7926     # don't restore from ebp
 7927     81 0/subop/add %esp 8/imm32
 7928     # . epilogue
 7929     5d/pop-to-ebp
 7930     c3/return
 7931 
 7932 test-copy-null-value-to-offset:
 7933     # . prologue
 7934     55/push-ebp
 7935     89/<- %ebp 4/r32/esp
 7936     # setup
 7937     (clear-stream _test-input-stream)
 7938     (clear-stream $_test-input-buffered-file->buffer)
 7939     (clear-stream _test-output-stream)
 7940     (clear-stream $_test-output-buffered-file->buffer)
 7941     #
 7942     (write _test-input-stream "fn foo {\n")
 7943     (write _test-input-stream "  var y/ecx: (offset int) <- copy 0\n")
 7944     (write _test-input-stream "}\n")
 7945     # convert
 7946     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7947     (flush _test-output-buffered-file)
 7948 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7954     # no errors
 7955     # . epilogue
 7956     89/<- %esp 5/r32/ebp
 7957     5d/pop-to-ebp
 7958     c3/return
 7959 
 7960 test-copy-non-literal-to-byte:
 7961     # . prologue
 7962     55/push-ebp
 7963     89/<- %ebp 4/r32/esp
 7964     # setup
 7965     (clear-stream _test-input-stream)
 7966     (clear-stream $_test-input-buffered-file->buffer)
 7967     (clear-stream _test-output-stream)
 7968     (clear-stream $_test-output-buffered-file->buffer)
 7969     (clear-stream _test-error-stream)
 7970     (clear-stream $_test-error-buffered-file->buffer)
 7971     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7972     68/push 0/imm32
 7973     68/push 0/imm32
 7974     89/<- %edx 4/r32/esp
 7975     (tailor-exit-descriptor %edx 0x10)
 7976     #
 7977     (write _test-input-stream "fn foo {\n")
 7978     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 7979     (write _test-input-stream "  var y/ecx: byte <- copy x\n")
 7980     (write _test-input-stream "}\n")
 7981     # convert
 7982     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7983     # registers except esp clobbered at this point
 7984     # restore ed
 7985     89/<- %edx 4/r32/esp
 7986     (flush _test-output-buffered-file)
 7987     (flush _test-error-buffered-file)
 7988 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7994     # check output
 7995     (check-stream-equal _test-output-stream  ""  "F - test-copy-non-literal-to-byte: output should be empty")
 7996     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy: cannot copy non-literal to 'y' of type byte; use copy-byte"  "F - test-copy-non-literal-to-byte: error message")
 7997     # check that stop(1) was called
 7998     (check-ints-equal *(edx+4) 2 "F - test-copy-non-literal-to-byte: exit status")
 7999     # don't restore from ebp
 8000     81 0/subop/add %esp 8/imm32
 8001     # . epilogue
 8002     5d/pop-to-ebp
 8003     c3/return
 8004 
 8005 test-copy-deref-address:
 8006     # . prologue
 8007     55/push-ebp
 8008     89/<- %ebp 4/r32/esp
 8009     # setup
 8010     (clear-stream _test-input-stream)
 8011     (clear-stream $_test-input-buffered-file->buffer)
 8012     (clear-stream _test-output-stream)
 8013     (clear-stream $_test-output-buffered-file->buffer)
 8014     #
 8015     (write _test-input-stream "fn foo {\n")
 8016     (write _test-input-stream "  var x/eax: (addr addr int) <- copy 0\n")
 8017     (write _test-input-stream "  var y/ecx: (addr int) <- copy *x\n")
 8018     (write _test-input-stream "}\n")
 8019     # convert
 8020     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 8021     (flush _test-output-buffered-file)
 8022     # no errors
 8023     # . epilogue
 8024     5d/pop-to-ebp
 8025     c3/return
 8026 
 8027 test-copy-to-non-register:
 8028     # . prologue
 8029     55/push-ebp
 8030     89/<- %ebp 4/r32/esp
 8031     # setup
 8032     (clear-stream _test-input-stream)
 8033     (clear-stream $_test-input-buffered-file->buffer)
 8034     (clear-stream _test-output-stream)
 8035     (clear-stream $_test-output-buffered-file->buffer)
 8036     (clear-stream _test-error-stream)
 8037     (clear-stream $_test-error-buffered-file->buffer)
 8038     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8039     68/push 0/imm32
 8040     68/push 0/imm32
 8041     89/<- %edx 4/r32/esp
 8042     (tailor-exit-descriptor %edx 0x10)
 8043     #
 8044     (write _test-input-stream "fn foo {\n")
 8045     (write _test-input-stream "  var x: int\n")
 8046     (write _test-input-stream "  x <- copy 0\n")
 8047     (write _test-input-stream "}\n")
 8048     # convert
 8049     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8050     # registers except esp clobbered at this point
 8051     # restore ed
 8052     89/<- %edx 4/r32/esp
 8053     (flush _test-output-buffered-file)
 8054     (flush _test-error-buffered-file)
 8055 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8061     # check output
 8062     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-non-register: output should be empty")
 8063     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy: output 'x' not in a register"  "F - test-copy-to-non-register: error message")
 8064     # check that stop(1) was called
 8065     (check-ints-equal *(edx+4) 2 "F - test-copy-to-non-register: exit status")
 8066     # don't restore from ebp
 8067     81 0/subop/add %esp 8/imm32
 8068     # . epilogue
 8069     5d/pop-to-ebp
 8070     c3/return
 8071 
 8072 test-copy-from-non-scalar-inout:
 8073     # . prologue
 8074     55/push-ebp
 8075     89/<- %ebp 4/r32/esp
 8076     # setup
 8077     (clear-stream _test-input-stream)
 8078     (clear-stream $_test-input-buffered-file->buffer)
 8079     (clear-stream _test-output-stream)
 8080     (clear-stream $_test-output-buffered-file->buffer)
 8081     (clear-stream _test-error-stream)
 8082     (clear-stream $_test-error-buffered-file->buffer)
 8083     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8084     68/push 0/imm32
 8085     68/push 0/imm32
 8086     89/<- %edx 4/r32/esp
 8087     (tailor-exit-descriptor %edx 0x10)
 8088     #
 8089     (write _test-input-stream "fn foo {\n")
 8090     (write _test-input-stream "  var x: (handle int)\n")
 8091     (write _test-input-stream "  var y/eax: int <- copy x\n")
 8092     (write _test-input-stream "}\n")
 8093     # convert
 8094     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8095     # registers except esp clobbered at this point
 8096     # restore ed
 8097     89/<- %edx 4/r32/esp
 8098     (flush _test-output-buffered-file)
 8099     (flush _test-error-buffered-file)
 8100 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8106     # check output
 8107     (check-stream-equal _test-output-stream  ""  "F - test-copy-from-non-scalar-inout: output should be empty")
 8108     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy: 'x' is too large to fit in a register"  "F - test-copy-from-non-scalar-inout: error message")
 8109     # check that stop(1) was called
 8110     (check-ints-equal *(edx+4) 2 "F - test-copy-from-non-scalar-inout: exit status")
 8111     # don't restore from ebp
 8112     81 0/subop/add %esp 8/imm32
 8113     # . epilogue
 8114     5d/pop-to-ebp
 8115     c3/return
 8116 
 8117 test-copy-to-with-no-inout:
 8118     # . prologue
 8119     55/push-ebp
 8120     89/<- %ebp 4/r32/esp
 8121     # setup
 8122     (clear-stream _test-input-stream)
 8123     (clear-stream $_test-input-buffered-file->buffer)
 8124     (clear-stream _test-output-stream)
 8125     (clear-stream $_test-output-buffered-file->buffer)
 8126     (clear-stream _test-error-stream)
 8127     (clear-stream $_test-error-buffered-file->buffer)
 8128     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8129     68/push 0/imm32
 8130     68/push 0/imm32
 8131     89/<- %edx 4/r32/esp
 8132     (tailor-exit-descriptor %edx 0x10)
 8133     #
 8134     (write _test-input-stream "fn foo {\n")
 8135     (write _test-input-stream "  copy-to\n")
 8136     (write _test-input-stream "}\n")
 8137     # convert
 8138     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8139     # registers except esp clobbered at this point
 8140     # restore ed
 8141     89/<- %edx 4/r32/esp
 8142     (flush _test-output-buffered-file)
 8143     (flush _test-error-buffered-file)
 8144 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8150     # check output
 8151     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-with-no-inout: output should be empty")
 8152     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-to' must have two inouts"  "F - test-copy-to-with-no-inout: error message")
 8153     # check that stop(1) was called
 8154     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-no-inout: exit status")
 8155     # don't restore from ebp
 8156     81 0/subop/add %esp 8/imm32
 8157     # . epilogue
 8158     5d/pop-to-ebp
 8159     c3/return
 8160 
 8161 test-copy-to-with-no-source:
 8162     # . prologue
 8163     55/push-ebp
 8164     89/<- %ebp 4/r32/esp
 8165     # setup
 8166     (clear-stream _test-input-stream)
 8167     (clear-stream $_test-input-buffered-file->buffer)
 8168     (clear-stream _test-output-stream)
 8169     (clear-stream $_test-output-buffered-file->buffer)
 8170     (clear-stream _test-error-stream)
 8171     (clear-stream $_test-error-buffered-file->buffer)
 8172     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8173     68/push 0/imm32
 8174     68/push 0/imm32
 8175     89/<- %edx 4/r32/esp
 8176     (tailor-exit-descriptor %edx 0x10)
 8177     #
 8178     (write _test-input-stream "fn foo {\n")
 8179     (write _test-input-stream "  var x: boolean\n")
 8180     (write _test-input-stream "  copy-to x\n")
 8181     (write _test-input-stream "}\n")
 8182     # convert
 8183     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8184     # registers except esp clobbered at this point
 8185     # restore ed
 8186     89/<- %edx 4/r32/esp
 8187     (flush _test-output-buffered-file)
 8188     (flush _test-error-buffered-file)
 8189 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8195     # check output
 8196     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-with-no-source: output should be empty")
 8197     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-to' must have two inouts"  "F - test-copy-to-with-no-source: error message")
 8198     # check that stop(1) was called
 8199     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-no-source: exit status")
 8200     # don't restore from ebp
 8201     81 0/subop/add %esp 8/imm32
 8202     # . epilogue
 8203     5d/pop-to-ebp
 8204     c3/return
 8205 
 8206 test-copy-to-with-no-register:
 8207     # . prologue
 8208     55/push-ebp
 8209     89/<- %ebp 4/r32/esp
 8210     # setup
 8211     (clear-stream _test-input-stream)
 8212     (clear-stream $_test-input-buffered-file->buffer)
 8213     (clear-stream _test-output-stream)
 8214     (clear-stream $_test-output-buffered-file->buffer)
 8215     (clear-stream _test-error-stream)
 8216     (clear-stream $_test-error-buffered-file->buffer)
 8217     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8218     68/push 0/imm32
 8219     68/push 0/imm32
 8220     89/<- %edx 4/r32/esp
 8221     (tailor-exit-descriptor %edx 0x10)
 8222     #
 8223     (write _test-input-stream "fn foo {\n")
 8224     (write _test-input-stream "  var x: boolean\n")
 8225     (write _test-input-stream "  copy-to x, x\n")
 8226     (write _test-input-stream "}\n")
 8227     # convert
 8228     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8229     # registers except esp clobbered at this point
 8230     # restore ed
 8231     89/<- %edx 4/r32/esp
 8232     (flush _test-output-buffered-file)
 8233     (flush _test-error-buffered-file)
 8234 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8240     # check output
 8241     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-with-no-register: output should be empty")
 8242     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-to: source (second inout) is in memory"  "F - test-copy-to-with-no-register: error message")
 8243     # check that stop(1) was called
 8244     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-no-register: exit status")
 8245     # don't restore from ebp
 8246     81 0/subop/add %esp 8/imm32
 8247     # . epilogue
 8248     5d/pop-to-ebp
 8249     c3/return
 8250 
 8251 test-copy-to-with-too-many-inouts:
 8252     # . prologue
 8253     55/push-ebp
 8254     89/<- %ebp 4/r32/esp
 8255     # setup
 8256     (clear-stream _test-input-stream)
 8257     (clear-stream $_test-input-buffered-file->buffer)
 8258     (clear-stream _test-output-stream)
 8259     (clear-stream $_test-output-buffered-file->buffer)
 8260     (clear-stream _test-error-stream)
 8261     (clear-stream $_test-error-buffered-file->buffer)
 8262     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8263     68/push 0/imm32
 8264     68/push 0/imm32
 8265     89/<- %edx 4/r32/esp
 8266     (tailor-exit-descriptor %edx 0x10)
 8267     #
 8268     (write _test-input-stream "fn foo {\n")
 8269     (write _test-input-stream "  var x: boolean\n")
 8270     (write _test-input-stream "  copy-to x, 0, 0\n")
 8271     (write _test-input-stream "}\n")
 8272     # convert
 8273     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8274     # registers except esp clobbered at this point
 8275     # restore ed
 8276     89/<- %edx 4/r32/esp
 8277     (flush _test-output-buffered-file)
 8278     (flush _test-error-buffered-file)
 8279 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8285     # check output
 8286     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-with-too-many-inouts: output should be empty")
 8287     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-to' must have two inouts"  "F - test-copy-to-with-too-many-inouts: error message")
 8288     # check that stop(1) was called
 8289     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-too-many-inouts: exit status")
 8290     # don't restore from ebp
 8291     81 0/subop/add %esp 8/imm32
 8292     # . epilogue
 8293     5d/pop-to-ebp
 8294     c3/return
 8295 
 8296 test-copy-to-with-output:
 8297     # . prologue
 8298     55/push-ebp
 8299     89/<- %ebp 4/r32/esp
 8300     # setup
 8301     (clear-stream _test-input-stream)
 8302     (clear-stream $_test-input-buffered-file->buffer)
 8303     (clear-stream _test-output-stream)
 8304     (clear-stream $_test-output-buffered-file->buffer)
 8305     (clear-stream _test-error-stream)
 8306     (clear-stream $_test-error-buffered-file->buffer)
 8307     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8308     68/push 0/imm32
 8309     68/push 0/imm32
 8310     89/<- %edx 4/r32/esp
 8311     (tailor-exit-descriptor %edx 0x10)
 8312     #
 8313     (write _test-input-stream "fn foo {\n")
 8314     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
 8315     (write _test-input-stream "  var y/ecx: boolean <- copy 0\n")
 8316     (write _test-input-stream "  x <- copy-to y, 0\n")
 8317     (write _test-input-stream "}\n")
 8318     # convert
 8319     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8320     # registers except esp clobbered at this point
 8321     # restore ed
 8322     89/<- %edx 4/r32/esp
 8323     (flush _test-output-buffered-file)
 8324     (flush _test-error-buffered-file)
 8325 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8331     # check output
 8332     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-with-output: output should be empty")
 8333     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-to' must not have any outputs"  "F - test-copy-to-with-output: error message")
 8334     # check that stop(1) was called
 8335     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-output: exit status")
 8336     # don't restore from ebp
 8337     81 0/subop/add %esp 8/imm32
 8338     # . epilogue
 8339     5d/pop-to-ebp
 8340     c3/return
 8341 
 8342 test-copy-to-invalid-value-to-address:
 8343     # . prologue
 8344     55/push-ebp
 8345     89/<- %ebp 4/r32/esp
 8346     # setup
 8347     (clear-stream _test-input-stream)
 8348     (clear-stream $_test-input-buffered-file->buffer)
 8349     (clear-stream _test-output-stream)
 8350     (clear-stream $_test-output-buffered-file->buffer)
 8351     (clear-stream _test-error-stream)
 8352     (clear-stream $_test-error-buffered-file->buffer)
 8353     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8354     68/push 0/imm32
 8355     68/push 0/imm32
 8356     89/<- %edx 4/r32/esp
 8357     (tailor-exit-descriptor %edx 0x10)
 8358     #
 8359     (write _test-input-stream "fn foo {\n")
 8360     (write _test-input-stream "  var x/eax: int <- copy 0\n")
 8361     (write _test-input-stream "  var y: (addr int)\n")
 8362     (write _test-input-stream "  copy-to y, x\n")
 8363     (write _test-input-stream "}\n")
 8364     # convert
 8365     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8366     # registers except esp clobbered at this point
 8367     # restore ed
 8368     89/<- %edx 4/r32/esp
 8369     (flush _test-output-buffered-file)
 8370     (flush _test-error-buffered-file)
 8371 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8377     # check output
 8378     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-invalid-value-to-address: output should be empty")
 8379     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-to: 'y' must be a non-addr non-offset scalar"  "F - test-copy-to-invalid-value-to-address: error message")
 8380     # check that stop(1) was called
 8381     (check-ints-equal *(edx+4) 2 "F - test-copy-to-invalid-value-to-address: exit status")
 8382     # don't restore from ebp
 8383     81 0/subop/add %esp 8/imm32
 8384     # . epilogue
 8385     5d/pop-to-ebp
 8386     c3/return
 8387 
 8388 test-copy-to-null-value-to-address:
 8389     # . prologue
 8390     55/push-ebp
 8391     89/<- %ebp 4/r32/esp
 8392     # setup
 8393     (clear-stream _test-input-stream)
 8394     (clear-stream $_test-input-buffered-file->buffer)
 8395     (clear-stream _test-output-stream)
 8396     (clear-stream $_test-output-buffered-file->buffer)
 8397     #
 8398     (write _test-input-stream "fn foo {\n")
 8399     (write _test-input-stream "  var y: (addr int)\n")
 8400     (write _test-input-stream "  copy-to y, 0\n")
 8401     (write _test-input-stream "}\n")
 8402     # convert
 8403     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 8404     (flush _test-output-buffered-file)
 8405     # no errors
 8406     # . epilogue
 8407     89/<- %esp 5/r32/ebp
 8408     5d/pop-to-ebp
 8409     c3/return
 8410 
 8411 test-copy-to-invalid-value-to-offset:
 8412     # . prologue
 8413     55/push-ebp
 8414     89/<- %ebp 4/r32/esp
 8415     # setup
 8416     (clear-stream _test-input-stream)
 8417     (clear-stream $_test-input-buffered-file->buffer)
 8418     (clear-stream _test-output-stream)
 8419     (clear-stream $_test-output-buffered-file->buffer)
 8420     (clear-stream _test-error-stream)
 8421     (clear-stream $_test-error-buffered-file->buffer)
 8422     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8423     68/push 0/imm32
 8424     68/push 0/imm32
 8425     89/<- %edx 4/r32/esp
 8426     (tailor-exit-descriptor %edx 0x10)
 8427     #
 8428     (write _test-input-stream "fn foo {\n")
 8429     (write _test-input-stream "  var x/eax: int <- copy 0\n")
 8430     (write _test-input-stream "  var y: (offset int)\n")
 8431     (write _test-input-stream "  copy-to y, x\n")
 8432     (write _test-input-stream "}\n")
 8433     # convert
 8434     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8435     # registers except esp clobbered at this point
 8436     # restore ed
 8437     89/<- %edx 4/r32/esp
 8438     (flush _test-output-buffered-file)
 8439     (flush _test-error-buffered-file)
 8440 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8446     # check output
 8447     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-invalid-value-to-offset: output should be empty")
 8448     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-to: 'y' must be a non-addr non-offset scalar"  "F - test-copy-to-invalid-value-to-offset: error message")
 8449     # check that stop(1) was called
 8450     (check-ints-equal *(edx+4) 2 "F - test-copy-to-invalid-value-to-offset: exit status")
 8451     # don't restore from ebp
 8452     81 0/subop/add %esp 8/imm32
 8453     # . epilogue
 8454     5d/pop-to-ebp
 8455     c3/return
 8456 
 8457 test-copy-to-null-value-to-offset:
 8458     # . prologue
 8459     55/push-ebp
 8460     89/<- %ebp 4/r32/esp
 8461     # setup
 8462     (clear-stream _test-input-stream)
 8463     (clear-stream $_test-input-buffered-file->buffer)
 8464     (clear-stream _test-output-stream)
 8465     (clear-stream $_test-output-buffered-file->buffer)
 8466     #
 8467     (write _test-input-stream "fn foo {\n")
 8468     (write _test-input-stream "  var y: (offset int)\n")
 8469     (write _test-input-stream "  copy-to y, 0\n")
 8470     (write _test-input-stream "}\n")
 8471     # convert
 8472     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 8473     (flush _test-output-buffered-file)
 8474     # no errors
 8475     # . epilogue
 8476     89/<- %esp 5/r32/ebp
 8477     5d/pop-to-ebp
 8478     c3/return
 8479 
 8480 test-copy-to-non-literal-to-byte:
 8481     # . prologue
 8482     55/push-ebp
 8483     89/<- %ebp 4/r32/esp
 8484     # setup
 8485     (clear-stream _test-input-stream)
 8486     (clear-stream $_test-input-buffered-file->buffer)
 8487     (clear-stream _test-output-stream)
 8488     (clear-stream $_test-output-buffered-file->buffer)
 8489     (clear-stream _test-error-stream)
 8490     (clear-stream $_test-error-buffered-file->buffer)
 8491     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8492     68/push 0/imm32
 8493     68/push 0/imm32
 8494     89/<- %edx 4/r32/esp
 8495     (tailor-exit-descriptor %edx 0x10)
 8496     #
 8497     (write _test-input-stream "fn foo {\n")
 8498     (write _test-input-stream "  var x/ecx: byte <- copy 3\n")
 8499     (write _test-input-stream "  var y/eax: (addr byte) <- copy 0\n")
 8500     (write _test-input-stream "  copy-to *y, x\n")
 8501     (write _test-input-stream "}\n")
 8502     # convert
 8503     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8504     # registers except esp clobbered at this point
 8505     # restore ed
 8506     89/<- %edx 4/r32/esp
 8507     (flush _test-output-buffered-file)
 8508     (flush _test-error-buffered-file)
 8509 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8515     # check output
 8516     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-non-literal-to-byte: output should be empty")
 8517     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-to: cannot copy non-literal to type byte; use copy-byte-to"  "F - test-copy-to-non-literal-to-byte: error message")
 8518     # check that stop(1) was called
 8519     (check-ints-equal *(edx+4) 2 "F - test-copy-to-non-literal-to-byte: exit status")
 8520     # don't restore from ebp
 8521     81 0/subop/add %esp 8/imm32
 8522     # . epilogue
 8523     5d/pop-to-ebp
 8524     c3/return
 8525 
 8526 test-copy-to-deref-address:
 8527     # . prologue
 8528     55/push-ebp
 8529     89/<- %ebp 4/r32/esp
 8530     # setup
 8531     (clear-stream _test-input-stream)
 8532     (clear-stream $_test-input-buffered-file->buffer)
 8533     (clear-stream _test-output-stream)
 8534     (clear-stream $_test-output-buffered-file->buffer)
 8535     #
 8536     (write _test-input-stream "fn foo {\n")
 8537     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
 8538     (write _test-input-stream "  var y/ecx: (addr addr int) <- copy 0\n")
 8539     (write _test-input-stream "  copy-to *y, x\n")
 8540     (write _test-input-stream "}\n")
 8541     # convert
 8542     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 8543     (flush _test-output-buffered-file)
 8544     # no errors
 8545     # . epilogue
 8546     5d/pop-to-ebp
 8547     c3/return
 8548 
 8549 test-copy-to-from-non-scalar-inout:
 8550     # . prologue
 8551     55/push-ebp
 8552     89/<- %ebp 4/r32/esp
 8553     # setup
 8554     (clear-stream _test-input-stream)
 8555     (clear-stream $_test-input-buffered-file->buffer)
 8556     (clear-stream _test-output-stream)
 8557     (clear-stream $_test-output-buffered-file->buffer)
 8558     (clear-stream _test-error-stream)
 8559     (clear-stream $_test-error-buffered-file->buffer)
 8560     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8561     68/push 0/imm32
 8562     68/push 0/imm32
 8563     89/<- %edx 4/r32/esp
 8564     (tailor-exit-descriptor %edx 0x10)
 8565     #
 8566     (write _test-input-stream "fn foo {\n")
 8567     (write _test-input-stream "  var x: (handle int)\n")
 8568     (write _test-input-stream "  var y: int\n")
 8569     (write _test-input-stream "  copy-to y, x\n")
 8570     (write _test-input-stream "}\n")
 8571     # convert
 8572     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8573     # registers except esp clobbered at this point
 8574     # restore ed
 8575     89/<- %edx 4/r32/esp
 8576     (flush _test-output-buffered-file)
 8577     (flush _test-error-buffered-file)
 8578 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8584     # check output
 8585     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-from-non-scalar-inout: output should be empty")
 8586     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-to: 'x' is too large to copy"  "F - test-copy-to-from-non-scalar-inout: error message")
 8587     # check that stop(1) was called
 8588     (check-ints-equal *(edx+4) 2 "F - test-copy-to-from-non-scalar-inout: exit status")
 8589     # don't restore from ebp
 8590     81 0/subop/add %esp 8/imm32
 8591     # . epilogue
 8592     5d/pop-to-ebp
 8593     c3/return
 8594 
 8595 test-copy-byte-with-no-inout:
 8596     # . prologue
 8597     55/push-ebp
 8598     89/<- %ebp 4/r32/esp
 8599     # setup
 8600     (clear-stream _test-input-stream)
 8601     (clear-stream $_test-input-buffered-file->buffer)
 8602     (clear-stream _test-output-stream)
 8603     (clear-stream $_test-output-buffered-file->buffer)
 8604     (clear-stream _test-error-stream)
 8605     (clear-stream $_test-error-buffered-file->buffer)
 8606     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8607     68/push 0/imm32
 8608     68/push 0/imm32
 8609     89/<- %edx 4/r32/esp
 8610     (tailor-exit-descriptor %edx 0x10)
 8611     #
 8612     (write _test-input-stream "fn foo {\n")
 8613     (write _test-input-stream "  var x/eax: byte <- copy-byte\n")
 8614     (write _test-input-stream "}\n")
 8615     # convert
 8616     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8617     # registers except esp clobbered at this point
 8618     # restore ed
 8619     89/<- %edx 4/r32/esp
 8620     (flush _test-output-buffered-file)
 8621     (flush _test-error-buffered-file)
 8622 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8628     # check output
 8629     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-with-no-inout: output should be empty")
 8630     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-byte' expects an inout"  "F - test-copy-byte-with-no-inout: error message")
 8631     # check that stop(1) was called
 8632     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-with-no-inout: exit status")
 8633     # don't restore from ebp
 8634     81 0/subop/add %esp 8/imm32
 8635     # . epilogue
 8636     5d/pop-to-ebp
 8637     c3/return
 8638 
 8639 test-copy-byte-with-multiple-inouts:
 8640     # . prologue
 8641     55/push-ebp
 8642     89/<- %ebp 4/r32/esp
 8643     # setup
 8644     (clear-stream _test-input-stream)
 8645     (clear-stream $_test-input-buffered-file->buffer)
 8646     (clear-stream _test-output-stream)
 8647     (clear-stream $_test-output-buffered-file->buffer)
 8648     (clear-stream _test-error-stream)
 8649     (clear-stream $_test-error-buffered-file->buffer)
 8650     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8651     68/push 0/imm32
 8652     68/push 0/imm32
 8653     89/<- %edx 4/r32/esp
 8654     (tailor-exit-descriptor %edx 0x10)
 8655     #
 8656     (write _test-input-stream "fn foo {\n")
 8657     (write _test-input-stream "  var x/eax: byte <- copy-byte 0, 0\n")
 8658     (write _test-input-stream "}\n")
 8659     # convert
 8660     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8661     # registers except esp clobbered at this point
 8662     # restore ed
 8663     89/<- %edx 4/r32/esp
 8664     (flush _test-output-buffered-file)
 8665     (flush _test-error-buffered-file)
 8666 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8672     # check output
 8673     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-with-multiple-inouts: output should be empty")
 8674     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-byte' must have just one inout"  "F - test-copy-byte-with-multiple-inouts: error message")
 8675     # check that stop(1) was called
 8676     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-with-multiple-inouts: exit status")
 8677     # don't restore from ebp
 8678     81 0/subop/add %esp 8/imm32
 8679     # . epilogue
 8680     5d/pop-to-ebp
 8681     c3/return
 8682 
 8683 test-copy-byte-with-no-output:
 8684     # . prologue
 8685     55/push-ebp
 8686     89/<- %ebp 4/r32/esp
 8687     # setup
 8688     (clear-stream _test-input-stream)
 8689     (clear-stream $_test-input-buffered-file->buffer)
 8690     (clear-stream _test-output-stream)
 8691     (clear-stream $_test-output-buffered-file->buffer)
 8692     (clear-stream _test-error-stream)
 8693     (clear-stream $_test-error-buffered-file->buffer)
 8694     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8695     68/push 0/imm32
 8696     68/push 0/imm32
 8697     89/<- %edx 4/r32/esp
 8698     (tailor-exit-descriptor %edx 0x10)
 8699     #
 8700     (write _test-input-stream "fn foo {\n")
 8701     (write _test-input-stream "  copy-byte 0\n")
 8702     (write _test-input-stream "}\n")
 8703     # convert
 8704     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8705     # registers except esp clobbered at this point
 8706     # restore ed
 8707     89/<- %edx 4/r32/esp
 8708     (flush _test-output-buffered-file)
 8709     (flush _test-error-buffered-file)
 8710 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8716     # check output
 8717     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-with-no-output: output should be empty")
 8718     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-byte' expects an output"  "F - test-copy-byte-with-no-output: error message")
 8719     # check that stop(1) was called
 8720     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-with-no-output: exit status")
 8721     # don't restore from ebp
 8722     81 0/subop/add %esp 8/imm32
 8723     # . epilogue
 8724     5d/pop-to-ebp
 8725     c3/return
 8726 
 8727 test-copy-byte-with-multiple-outputs:
 8728     # . prologue
 8729     55/push-ebp
 8730     89/<- %ebp 4/r32/esp
 8731     # setup
 8732     (clear-stream _test-input-stream)
 8733     (clear-stream $_test-input-buffered-file->buffer)
 8734     (clear-stream _test-output-stream)
 8735     (clear-stream $_test-output-buffered-file->buffer)
 8736     (clear-stream _test-error-stream)
 8737     (clear-stream $_test-error-buffered-file->buffer)
 8738     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8739     68/push 0/imm32
 8740     68/push 0/imm32
 8741     89/<- %edx 4/r32/esp
 8742     (tailor-exit-descriptor %edx 0x10)
 8743     #
 8744     (write _test-input-stream "fn foo {\n")
 8745     (write _test-input-stream "  var x/eax: byte <- copy 0\n")
 8746     (write _test-input-stream "  var y/ecx: byte <- copy 0\n")
 8747     (write _test-input-stream "  x, y <- copy-byte 0\n")
 8748     (write _test-input-stream "}\n")
 8749     # convert
 8750     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8751     # registers except esp clobbered at this point
 8752     # restore ed
 8753     89/<- %edx 4/r32/esp
 8754     (flush _test-output-buffered-file)
 8755     (flush _test-error-buffered-file)
 8756 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8762     # check output
 8763     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-with-multiple-outputs: output should be empty")
 8764     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-byte' must have just one output"  "F - test-copy-byte-with-multiple-outputs: error message")
 8765     # check that stop(1) was called
 8766     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-with-multiple-outputs: exit status")
 8767     # don't restore from ebp
 8768     81 0/subop/add %esp 8/imm32
 8769     # . epilogue
 8770     5d/pop-to-ebp
 8771     c3/return
 8772 
 8773 test-copy-byte-deref-address:
 8774     # . prologue
 8775     55/push-ebp
 8776     89/<- %ebp 4/r32/esp
 8777     # setup
 8778     (clear-stream _test-input-stream)
 8779     (clear-stream $_test-input-buffered-file->buffer)
 8780     (clear-stream _test-output-stream)
 8781     (clear-stream $_test-output-buffered-file->buffer)
 8782     #
 8783     (write _test-input-stream "fn foo {\n")
 8784     (write _test-input-stream "  var x/eax: (addr byte) <- copy 0\n")
 8785     (write _test-input-stream "  var y/ecx: byte <- copy-byte *x\n")
 8786     (write _test-input-stream "}\n")
 8787     # convert
 8788     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 8789     (flush _test-output-buffered-file)
 8790 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8796     # not bothering checking output
 8797     (check-next-stream-line-equal _test-error-stream  ""  "F - test-copy-byte-deref-address: error message")
 8798     # . epilogue
 8799     5d/pop-to-ebp
 8800     c3/return
 8801 
 8802 test-copy-byte-with-invalid-output-type:
 8803     # . prologue
 8804     55/push-ebp
 8805     89/<- %ebp 4/r32/esp
 8806     # setup
 8807     (clear-stream _test-input-stream)
 8808     (clear-stream $_test-input-buffered-file->buffer)
 8809     (clear-stream _test-output-stream)
 8810     (clear-stream $_test-output-buffered-file->buffer)
 8811     (clear-stream _test-error-stream)
 8812     (clear-stream $_test-error-buffered-file->buffer)
 8813     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8814     68/push 0/imm32
 8815     68/push 0/imm32
 8816     89/<- %edx 4/r32/esp
 8817     (tailor-exit-descriptor %edx 0x10)
 8818     #
 8819     (write _test-input-stream "fn foo {\n")
 8820     (write _test-input-stream "  var x/eax: (addr byte) <- copy 0\n")
 8821     (write _test-input-stream "  var y/eax: int <- copy-byte *x\n")
 8822     (write _test-input-stream "}\n")
 8823     # convert
 8824     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8825     # registers except esp clobbered at this point
 8826     # restore ed
 8827     89/<- %edx 4/r32/esp
 8828     (flush _test-output-buffered-file)
 8829     (flush _test-error-buffered-file)
 8830 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8836     # check output
 8837     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-with-invalid-output-type: output should be empty")
 8838     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-byte' must write to output of type byte"  "F - test-copy-byte-with-invalid-output-type: error message")
 8839     # check that stop(1) was called
 8840     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-with-invalid-output-type: exit status")
 8841     # don't restore from ebp
 8842     81 0/subop/add %esp 8/imm32
 8843     # . epilogue
 8844     5d/pop-to-ebp
 8845     c3/return
 8846 
 8847 test-copy-byte-from-non-scalar-inout:
 8848     # . prologue
 8849     55/push-ebp
 8850     89/<- %ebp 4/r32/esp
 8851     # setup
 8852     (clear-stream _test-input-stream)
 8853     (clear-stream $_test-input-buffered-file->buffer)
 8854     (clear-stream _test-output-stream)
 8855     (clear-stream $_test-output-buffered-file->buffer)
 8856     (clear-stream _test-error-stream)
 8857     (clear-stream $_test-error-buffered-file->buffer)
 8858     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8859     68/push 0/imm32
 8860     68/push 0/imm32
 8861     89/<- %edx 4/r32/esp
 8862     (tailor-exit-descriptor %edx 0x10)
 8863     #
 8864     (write _test-input-stream "fn foo {\n")
 8865     (write _test-input-stream "  var x: (handle int)\n")
 8866     (write _test-input-stream "  var y/eax: byte <- copy-byte x\n")
 8867     (write _test-input-stream "}\n")
 8868     # convert
 8869     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8870     # registers except esp clobbered at this point
 8871     # restore ed
 8872     89/<- %edx 4/r32/esp
 8873     (flush _test-output-buffered-file)
 8874     (flush _test-error-buffered-file)
 8875 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8881     # check output
 8882     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-from-non-scalar-inout: output should be empty")
 8883     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-byte: 'x' is too large to fit in a register"  "F - test-copy-byte-from-non-scalar-inout: error message")
 8884     # check that stop(1) was called
 8885     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-from-non-scalar-inout: exit status")
 8886     # don't restore from ebp
 8887     81 0/subop/add %esp 8/imm32
 8888     # . epilogue
 8889     5d/pop-to-ebp
 8890     c3/return
 8891 
 8892 test-copy-byte-to-with-no-inout:
 8893     # . prologue
 8894     55/push-ebp
 8895     89/<- %ebp 4/r32/esp
 8896     # setup
 8897     (clear-stream _test-input-stream)
 8898     (clear-stream $_test-input-buffered-file->buffer)
 8899     (clear-stream _test-output-stream)
 8900     (clear-stream $_test-output-buffered-file->buffer)
 8901     (clear-stream _test-error-stream)
 8902     (clear-stream $_test-error-buffered-file->buffer)
 8903     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8904     68/push 0/imm32
 8905     68/push 0/imm32
 8906     89/<- %edx 4/r32/esp
 8907     (tailor-exit-descriptor %edx 0x10)
 8908     #
 8909     (write _test-input-stream "fn foo {\n")
 8910     (write _test-input-stream "  copy-byte-to\n")
 8911     (write _test-input-stream "}\n")
 8912     # convert
 8913     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8914     # registers except esp clobbered at this point
 8915     # restore ed
 8916     89/<- %edx 4/r32/esp
 8917     (flush _test-output-buffered-file)
 8918     (flush _test-error-buffered-file)
 8919 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8925     # check output
 8926     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-to-with-no-inout: output should be empty")
 8927     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-byte-to' must have two inouts"  "F - test-copy-byte-to-with-no-inout: error message")
 8928     # check that stop(1) was called
 8929     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-with-no-inout: exit status")
 8930     # don't restore from ebp
 8931     81 0/subop/add %esp 8/imm32
 8932     # . epilogue
 8933     5d/pop-to-ebp
 8934     c3/return
 8935 
 8936 test-copy-byte-to-with-no-source:
 8937     # . prologue
 8938     55/push-ebp
 8939     89/<- %ebp 4/r32/esp
 8940     # setup
 8941     (clear-stream _test-input-stream)
 8942     (clear-stream $_test-input-buffered-file->buffer)
 8943     (clear-stream _test-output-stream)
 8944     (clear-stream $_test-output-buffered-file->buffer)
 8945     (clear-stream _test-error-stream)
 8946     (clear-stream $_test-error-buffered-file->buffer)
 8947     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8948     68/push 0/imm32
 8949     68/push 0/imm32
 8950     89/<- %edx 4/r32/esp
 8951     (tailor-exit-descriptor %edx 0x10)
 8952     #
 8953     (write _test-input-stream "fn foo {\n")
 8954     (write _test-input-stream "  var x/eax: (addr byte) <- copy 0\n")
 8955     (write _test-input-stream "  copy-byte-to *x\n")
 8956     (write _test-input-stream "}\n")
 8957     # convert
 8958     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8959     # registers except esp clobbered at this point
 8960     # restore ed
 8961     89/<- %edx 4/r32/esp
 8962     (flush _test-output-buffered-file)
 8963     (flush _test-error-buffered-file)
 8964 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8970     # check output
 8971     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-to-with-no-source: output should be empty")
 8972     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-byte-to' must have two inouts"  "F - test-copy-byte-to-with-no-source: error message")
 8973     # check that stop(1) was called
 8974     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-with-no-source: exit status")
 8975     # don't restore from ebp
 8976     81 0/subop/add %esp 8/imm32
 8977     # . epilogue
 8978     5d/pop-to-ebp
 8979     c3/return
 8980 
 8981 test-copy-byte-to-with-too-many-inouts:
 8982     # . prologue
 8983     55/push-ebp
 8984     89/<- %ebp 4/r32/esp
 8985     # setup
 8986     (clear-stream _test-input-stream)
 8987     (clear-stream $_test-input-buffered-file->buffer)
 8988     (clear-stream _test-output-stream)
 8989     (clear-stream $_test-output-buffered-file->buffer)
 8990     (clear-stream _test-error-stream)
 8991     (clear-stream $_test-error-buffered-file->buffer)
 8992     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8993     68/push 0/imm32
 8994     68/push 0/imm32
 8995     89/<- %edx 4/r32/esp
 8996     (tailor-exit-descriptor %edx 0x10)
 8997     #
 8998     (write _test-input-stream "fn foo {\n")
 8999     (write _test-input-stream "  var x/eax: (addr byte) <- copy 0\n")
 9000     (write _test-input-stream "  copy-byte-to *x, 0, 0\n")
 9001     (write _test-input-stream "}\n")
 9002     # convert
 9003     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9004     # registers except esp clobbered at this point
 9005     # restore ed
 9006     89/<- %edx 4/r32/esp
 9007     (flush _test-output-buffered-file)
 9008     (flush _test-error-buffered-file)
 9009 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9015     # check output
 9016     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-to-with-too-many-inouts: output should be empty")
 9017     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-byte-to' must have two inouts"  "F - test-copy-byte-to-with-too-many-inouts: error message")
 9018     # check that stop(1) was called
 9019     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-with-too-many-inouts: exit status")
 9020     # don't restore from ebp
 9021     81 0/subop/add %esp 8/imm32
 9022     # . epilogue
 9023     5d/pop-to-ebp
 9024     c3/return
 9025 
 9026 test-copy-byte-to-with-output:
 9027     # . prologue
 9028     55/push-ebp
 9029     89/<- %ebp 4/r32/esp
 9030     # setup
 9031     (clear-stream _test-input-stream)
 9032     (clear-stream $_test-input-buffered-file->buffer)
 9033     (clear-stream _test-output-stream)
 9034     (clear-stream $_test-output-buffered-file->buffer)
 9035     (clear-stream _test-error-stream)
 9036     (clear-stream $_test-error-buffered-file->buffer)
 9037     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9038     68/push 0/imm32
 9039     68/push 0/imm32
 9040     89/<- %edx 4/r32/esp
 9041     (tailor-exit-descriptor %edx 0x10)
 9042     #
 9043     (write _test-input-stream "fn foo {\n")
 9044     (write _test-input-stream "  var x/eax: byte <- copy 0\n")
 9045     (write _test-input-stream "  var y/ecx: (addr byte) <- copy 0\n")
 9046     (write _test-input-stream "  x <- copy-byte-to *y, 0\n")
 9047     (write _test-input-stream "}\n")
 9048     # convert
 9049     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9050     # registers except esp clobbered at this point
 9051     # restore ed
 9052     89/<- %edx 4/r32/esp
 9053     (flush _test-output-buffered-file)
 9054     (flush _test-error-buffered-file)
 9055 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9061     # check output
 9062     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-to-with-output: output should be empty")
 9063     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-byte-to' must not have any outputs"  "F - test-copy-byte-to-with-output: error message")
 9064     # check that stop(1) was called
 9065     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-with-output: exit status")
 9066     # don't restore from ebp
 9067     81 0/subop/add %esp 8/imm32
 9068     # . epilogue
 9069     5d/pop-to-ebp
 9070     c3/return
 9071 
 9072 test-copy-byte-to-with-invalid-output-type:
 9073     # . prologue
 9074     55/push-ebp
 9075     89/<- %ebp 4/r32/esp
 9076     # setup
 9077     (clear-stream _test-input-stream)
 9078     (clear-stream $_test-input-buffered-file->buffer)
 9079     (clear-stream _test-output-stream)
 9080     (clear-stream $_test-output-buffered-file->buffer)
 9081     (clear-stream _test-error-stream)
 9082     (clear-stream $_test-error-buffered-file->buffer)
 9083     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9084     68/push 0/imm32
 9085     68/push 0/imm32
 9086     89/<- %edx 4/r32/esp
 9087     (tailor-exit-descriptor %edx 0x10)
 9088     #
 9089     (write _test-input-stream "fn foo {\n")
 9090     (write _test-input-stream "  var x/eax: byte <- copy 0\n")
 9091     (write _test-input-stream "  var y: int\n")
 9092     (write _test-input-stream "  copy-byte-to y, x\n")
 9093     (write _test-input-stream "}\n")
 9094     # convert
 9095     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9096     # registers except esp clobbered at this point
 9097     # restore ed
 9098     89/<- %edx 4/r32/esp
 9099     (flush _test-output-buffered-file)
 9100     (flush _test-error-buffered-file)
 9101 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9107     # check output
 9108     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-to-with-invalid-output-type: output should be empty")
 9109     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-byte-to: 'y' must be a byte"  "F - test-copy-byte-to-with-invalid-output-type: error message")
 9110     # check that stop(1) was called
 9111     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-with-invalid-output-type: exit status")
 9112     # don't restore from ebp
 9113     81 0/subop/add %esp 8/imm32
 9114     # . epilogue
 9115     5d/pop-to-ebp
 9116     c3/return
 9117 
 9118 test-copy-byte-to-with-literal-inout:
 9119     # . prologue
 9120     55/push-ebp
 9121     89/<- %ebp 4/r32/esp
 9122     # setup
 9123     (clear-stream _test-input-stream)
 9124     (clear-stream $_test-input-buffered-file->buffer)
 9125     (clear-stream _test-output-stream)
 9126     (clear-stream $_test-output-buffered-file->buffer)
 9127     (clear-stream _test-error-stream)
 9128     (clear-stream $_test-error-buffered-file->buffer)
 9129     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9130     68/push 0/imm32
 9131     68/push 0/imm32
 9132     89/<- %edx 4/r32/esp
 9133     (tailor-exit-descriptor %edx 0x10)
 9134     #
 9135     (write _test-input-stream "fn foo {\n")
 9136     (write _test-input-stream "  var x/eax: (addr byte) <- copy 0\n")
 9137     (write _test-input-stream "  copy-byte-to *x, 0\n")
 9138     (write _test-input-stream "}\n")
 9139     # convert
 9140     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9141     # registers except esp clobbered at this point
 9142     # restore ed
 9143     89/<- %edx 4/r32/esp
 9144     (flush _test-output-buffered-file)
 9145     (flush _test-error-buffered-file)
 9146 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9152     # check output
 9153     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-to-with-literal-inout: output should be empty")
 9154     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-byte-to: source (second inout) must be in a register"  "F - test-copy-byte-to-with-literal-inout: error message")
 9155     # check that stop(1) was called
 9156     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-with-literal-inout: exit status")
 9157     # don't restore from ebp
 9158     81 0/subop/add %esp 8/imm32
 9159     # . epilogue
 9160     5d/pop-to-ebp
 9161     c3/return
 9162 
 9163 test-copy-byte-to-deref-address:
 9164     # . prologue
 9165     55/push-ebp
 9166     89/<- %ebp 4/r32/esp
 9167     # setup
 9168     (clear-stream _test-input-stream)
 9169     (clear-stream $_test-input-buffered-file->buffer)
 9170     (clear-stream _test-output-stream)
 9171     (clear-stream $_test-output-buffered-file->buffer)
 9172     #
 9173     (write _test-input-stream "fn foo {\n")
 9174     (write _test-input-stream "  var x/eax: byte <- copy 0\n")
 9175     (write _test-input-stream "  var y/ecx: (addr byte) <- copy 0\n")
 9176     (write _test-input-stream "  copy-byte-to *y, x\n")
 9177     (write _test-input-stream "}\n")
 9178     # convert
 9179     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 9180     (flush _test-output-buffered-file)
 9181     # no errors
 9182     # . epilogue
 9183     5d/pop-to-ebp
 9184     c3/return
 9185 
 9186 test-copy-byte-to-from-non-scalar-inout:
 9187     # . prologue
 9188     55/push-ebp
 9189     89/<- %ebp 4/r32/esp
 9190     # setup
 9191     (clear-stream _test-input-stream)
 9192     (clear-stream $_test-input-buffered-file->buffer)
 9193     (clear-stream _test-output-stream)
 9194     (clear-stream $_test-output-buffered-file->buffer)
 9195     (clear-stream _test-error-stream)
 9196     (clear-stream $_test-error-buffered-file->buffer)
 9197     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9198     68/push 0/imm32
 9199     68/push 0/imm32
 9200     89/<- %edx 4/r32/esp
 9201     (tailor-exit-descriptor %edx 0x10)
 9202     #
 9203     (write _test-input-stream "fn foo {\n")
 9204     (write _test-input-stream "  var x: (handle int)\n")
 9205     (write _test-input-stream "  var y/eax: (addr byte) <- copy 0\n")
 9206     (write _test-input-stream "  copy-byte-to *y, x\n")
 9207     (write _test-input-stream "}\n")
 9208     # convert
 9209     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9210     # registers except esp clobbered at this point
 9211     # restore ed
 9212     89/<- %edx 4/r32/esp
 9213     (flush _test-output-buffered-file)
 9214     (flush _test-error-buffered-file)
 9215 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9221     # check output
 9222     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-to-from-non-scalar-inout: output should be empty")
 9223     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-byte-to: 'x' is too large to copy"  "F - test-copy-byte-to-from-non-scalar-inout: error message")
 9224     # check that stop(1) was called
 9225     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-from-non-scalar-inout: exit status")
 9226     # don't restore from ebp
 9227     81 0/subop/add %esp 8/imm32
 9228     # . epilogue
 9229     5d/pop-to-ebp
 9230     c3/return
 9231 
 9232 test-compare-with-no-inout:
 9233     # . prologue
 9234     55/push-ebp
 9235     89/<- %ebp 4/r32/esp
 9236     # setup
 9237     (clear-stream _test-input-stream)
 9238     (clear-stream $_test-input-buffered-file->buffer)
 9239     (clear-stream _test-output-stream)
 9240     (clear-stream $_test-output-buffered-file->buffer)
 9241     (clear-stream _test-error-stream)
 9242     (clear-stream $_test-error-buffered-file->buffer)
 9243     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9244     68/push 0/imm32
 9245     68/push 0/imm32
 9246     89/<- %edx 4/r32/esp
 9247     (tailor-exit-descriptor %edx 0x10)
 9248     #
 9249     (write _test-input-stream "fn foo {\n")
 9250     (write _test-input-stream "  var x: boolean\n")
 9251     (write _test-input-stream "  compare\n")
 9252     (write _test-input-stream "}\n")
 9253     # convert
 9254     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9255     # registers except esp clobbered at this point
 9256     # restore ed
 9257     89/<- %edx 4/r32/esp
 9258     (flush _test-output-buffered-file)
 9259     (flush _test-error-buffered-file)
 9260 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9266     # check output
 9267     (check-stream-equal _test-output-stream  ""  "F - test-compare-with-no-inout: output should be empty")
 9268     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'compare' must have two inouts"  "F - test-compare-with-no-inout: error message")
 9269     # check that stop(1) was called
 9270     (check-ints-equal *(edx+4) 2 "F - test-compare-with-no-inout: exit status")
 9271     # don't restore from ebp
 9272     81 0/subop/add %esp 8/imm32
 9273     # . epilogue
 9274     5d/pop-to-ebp
 9275     c3/return
 9276 
 9277 test-compare-with-just-one-inout:
 9278     # . prologue
 9279     55/push-ebp
 9280     89/<- %ebp 4/r32/esp
 9281     # setup
 9282     (clear-stream _test-input-stream)
 9283     (clear-stream $_test-input-buffered-file->buffer)
 9284     (clear-stream _test-output-stream)
 9285     (clear-stream $_test-output-buffered-file->buffer)
 9286     (clear-stream _test-error-stream)
 9287     (clear-stream $_test-error-buffered-file->buffer)
 9288     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9289     68/push 0/imm32
 9290     68/push 0/imm32
 9291     89/<- %edx 4/r32/esp
 9292     (tailor-exit-descriptor %edx 0x10)
 9293     #
 9294     (write _test-input-stream "fn foo {\n")
 9295     (write _test-input-stream "  var x: boolean\n")
 9296     (write _test-input-stream "  compare x\n")
 9297     (write _test-input-stream "}\n")
 9298     # convert
 9299     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9300     # registers except esp clobbered at this point
 9301     # restore ed
 9302     89/<- %edx 4/r32/esp
 9303     (flush _test-output-buffered-file)
 9304     (flush _test-error-buffered-file)
 9305 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9311     # check output
 9312     (check-stream-equal _test-output-stream  ""  "F - test-compare-with-just-one-inout: output should be empty")
 9313     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'compare' must have two inouts"  "F - test-compare-with-just-one-inout: error message")
 9314     # check that stop(1) was called
 9315     (check-ints-equal *(edx+4) 2 "F - test-compare-with-just-one-inout: exit status")
 9316     # don't restore from ebp
 9317     81 0/subop/add %esp 8/imm32
 9318     # . epilogue
 9319     5d/pop-to-ebp
 9320     c3/return
 9321 
 9322 test-compare-with-too-many-inouts:
 9323     # . prologue
 9324     55/push-ebp
 9325     89/<- %ebp 4/r32/esp
 9326     # setup
 9327     (clear-stream _test-input-stream)
 9328     (clear-stream $_test-input-buffered-file->buffer)
 9329     (clear-stream _test-output-stream)
 9330     (clear-stream $_test-output-buffered-file->buffer)
 9331     (clear-stream _test-error-stream)
 9332     (clear-stream $_test-error-buffered-file->buffer)
 9333     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9334     68/push 0/imm32
 9335     68/push 0/imm32
 9336     89/<- %edx 4/r32/esp
 9337     (tailor-exit-descriptor %edx 0x10)
 9338     #
 9339     (write _test-input-stream "fn foo {\n")
 9340     (write _test-input-stream "  var x: boolean\n")
 9341     (write _test-input-stream "  compare x, 0, 0\n")
 9342     (write _test-input-stream "}\n")
 9343     # convert
 9344     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9345     # registers except esp clobbered at this point
 9346     # restore ed
 9347     89/<- %edx 4/r32/esp
 9348     (flush _test-output-buffered-file)
 9349     (flush _test-error-buffered-file)
 9350 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9356     # check output
 9357     (check-stream-equal _test-output-stream  ""  "F - test-compare-with-too-many-inouts: output should be empty")
 9358     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'compare' must have two inouts"  "F - test-compare-with-too-many-inouts: error message")
 9359     # check that stop(1) was called
 9360     (check-ints-equal *(edx+4) 2 "F - test-compare-with-too-many-inouts: exit status")
 9361     # don't restore from ebp
 9362     81 0/subop/add %esp 8/imm32
 9363     # . epilogue
 9364     5d/pop-to-ebp
 9365     c3/return
 9366 
 9367 test-compare-with-output:
 9368     # . prologue
 9369     55/push-ebp
 9370     89/<- %ebp 4/r32/esp
 9371     # setup
 9372     (clear-stream _test-input-stream)
 9373     (clear-stream $_test-input-buffered-file->buffer)
 9374     (clear-stream _test-output-stream)
 9375     (clear-stream $_test-output-buffered-file->buffer)
 9376     (clear-stream _test-error-stream)
 9377     (clear-stream $_test-error-buffered-file->buffer)
 9378     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9379     68/push 0/imm32
 9380     68/push 0/imm32
 9381     89/<- %edx 4/r32/esp
 9382     (tailor-exit-descriptor %edx 0x10)
 9383     #
 9384     (write _test-input-stream "fn foo {\n")
 9385     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
 9386     (write _test-input-stream "  var y/ecx: boolean <- copy 0\n")
 9387     (write _test-input-stream "  x <- compare y, 0\n")
 9388     (write _test-input-stream "}\n")
 9389     # convert
 9390     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9391     # registers except esp clobbered at this point
 9392     # restore ed
 9393     89/<- %edx 4/r32/esp
 9394     (flush _test-output-buffered-file)
 9395     (flush _test-error-buffered-file)
 9396 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9402     # check output
 9403     (check-stream-equal _test-output-stream  ""  "F - test-compare-with-output: output should be empty")
 9404     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'compare' must not have any outputs"  "F - test-compare-with-output: error message")
 9405     # check that stop(1) was called
 9406     (check-ints-equal *(edx+4) 2 "F - test-compare-with-output: exit status")
 9407     # don't restore from ebp
 9408     81 0/subop/add %esp 8/imm32
 9409     # . epilogue
 9410     5d/pop-to-ebp
 9411     c3/return
 9412 
 9413 test-compare-invalid-value-to-address:
 9414     # . prologue
 9415     55/push-ebp
 9416     89/<- %ebp 4/r32/esp
 9417     # setup
 9418     (clear-stream _test-input-stream)
 9419     (clear-stream $_test-input-buffered-file->buffer)
 9420     (clear-stream _test-output-stream)
 9421     (clear-stream $_test-output-buffered-file->buffer)
 9422     (clear-stream _test-error-stream)
 9423     (clear-stream $_test-error-buffered-file->buffer)
 9424     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9425     68/push 0/imm32
 9426     68/push 0/imm32
 9427     89/<- %edx 4/r32/esp
 9428     (tailor-exit-descriptor %edx 0x10)
 9429     #
 9430     (write _test-input-stream "fn foo {\n")
 9431     (write _test-input-stream "  var x/eax: int <- copy 0\n")
 9432     (write _test-input-stream "  var y: (addr int)\n")
 9433     (write _test-input-stream "  compare y, x\n")
 9434     (write _test-input-stream "}\n")
 9435     # convert
 9436     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9437     # registers except esp clobbered at this point
 9438     # restore ed
 9439     89/<- %edx 4/r32/esp
 9440     (flush _test-output-buffered-file)
 9441     (flush _test-error-buffered-file)
 9442 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9448     # check output
 9449     (check-stream-equal _test-output-stream  ""  "F - test-compare-invalid-value-to-address: output should be empty")
 9450     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compare: 'y' must be a non-addr non-offset scalar"  "F - test-compare-invalid-value-to-address: error message")
 9451     # check that stop(1) was called
 9452     (check-ints-equal *(edx+4) 2 "F - test-compare-invalid-value-to-address: exit status")
 9453     # don't restore from ebp
 9454     81 0/subop/add %esp 8/imm32
 9455     # . epilogue
 9456     5d/pop-to-ebp
 9457     c3/return
 9458 
 9459 test-compare-address:
 9460     # . prologue
 9461     55/push-ebp
 9462     89/<- %ebp 4/r32/esp
 9463     # setup
 9464     (clear-stream _test-input-stream)
 9465     (clear-stream $_test-input-buffered-file->buffer)
 9466     (clear-stream _test-output-stream)
 9467     (clear-stream $_test-output-buffered-file->buffer)
 9468     #
 9469     (write _test-input-stream "fn foo {\n")
 9470     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
 9471     (write _test-input-stream "  var y/ecx: (addr int) <- copy 0\n")
 9472     (write _test-input-stream "  compare y, x\n")
 9473     (write _test-input-stream "}\n")
 9474     # convert
 9475     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 9476     (flush _test-output-buffered-file)
 9477     # no errors
 9478     # . epilogue
 9479     5d/pop-to-ebp
 9480     c3/return
 9481 
 9482 test-compare-deref-address:
 9483     # . prologue
 9484     55/push-ebp
 9485     89/<- %ebp 4/r32/esp
 9486     # setup
 9487     (clear-stream _test-input-stream)
 9488     (clear-stream $_test-input-buffered-file->buffer)
 9489     (clear-stream _test-output-stream)
 9490     (clear-stream $_test-output-buffered-file->buffer)
 9491     #
 9492     (write _test-input-stream "fn foo {\n")
 9493     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
 9494     (write _test-input-stream "  var y/ecx: (addr addr int) <- copy 0\n")
 9495     (write _test-input-stream "  compare *y, x\n")
 9496     (write _test-input-stream "}\n")
 9497     # convert
 9498     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 9499     (flush _test-output-buffered-file)
 9500     # no errors
 9501     # . epilogue
 9502     5d/pop-to-ebp
 9503     c3/return
 9504 
 9505 test-compare-two-vars-in-memory:
 9506     # . prologue
 9507     55/push-ebp
 9508     89/<- %ebp 4/r32/esp
 9509     # setup
 9510     (clear-stream _test-input-stream)
 9511     (clear-stream $_test-input-buffered-file->buffer)
 9512     (clear-stream _test-output-stream)
 9513     (clear-stream $_test-output-buffered-file->buffer)
 9514     (clear-stream _test-error-stream)
 9515     (clear-stream $_test-error-buffered-file->buffer)
 9516     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9517     68/push 0/imm32
 9518     68/push 0/imm32
 9519     89/<- %edx 4/r32/esp
 9520     (tailor-exit-descriptor %edx 0x10)
 9521     #
 9522     (write _test-input-stream "fn foo {\n")
 9523     (write _test-input-stream "  var x: boolean\n")
 9524     (write _test-input-stream "  compare x, x\n")
 9525     (write _test-input-stream "}\n")
 9526     # convert
 9527     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9528     # registers except esp clobbered at this point
 9529     # restore ed
 9530     89/<- %edx 4/r32/esp
 9531     (flush _test-output-buffered-file)
 9532     (flush _test-error-buffered-file)
 9533 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9539     # check output
 9540     (check-stream-equal _test-output-stream  ""  "F - test-compare-two-vars-in-memory: output should be empty")
 9541     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compare: both inouts are in memory"  "F - test-compare-two-vars-in-memory: error message")
 9542     # check that stop(1) was called
 9543     (check-ints-equal *(edx+4) 2 "F - test-compare-two-vars-in-memory: exit status")
 9544     # don't restore from ebp
 9545     81 0/subop/add %esp 8/imm32
 9546     # . epilogue
 9547     5d/pop-to-ebp
 9548     c3/return
 9549 
 9550 test-compare-non-scalar:
 9551     # . prologue
 9552     55/push-ebp
 9553     89/<- %ebp 4/r32/esp
 9554     # setup
 9555     (clear-stream _test-input-stream)
 9556     (clear-stream $_test-input-buffered-file->buffer)
 9557     (clear-stream _test-output-stream)
 9558     (clear-stream $_test-output-buffered-file->buffer)
 9559     (clear-stream _test-error-stream)
 9560     (clear-stream $_test-error-buffered-file->buffer)
 9561     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9562     68/push 0/imm32
 9563     68/push 0/imm32
 9564     89/<- %edx 4/r32/esp
 9565     (tailor-exit-descriptor %edx 0x10)
 9566     #
 9567     (write _test-input-stream "fn foo {\n")
 9568     (write _test-input-stream "  var x: (handle int)\n")
 9569     (write _test-input-stream "  var y: int\n")
 9570     (write _test-input-stream "  compare y, x\n")
 9571     (write _test-input-stream "}\n")
 9572     # convert
 9573     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9574     # registers except esp clobbered at this point
 9575     # restore ed
 9576     89/<- %edx 4/r32/esp
 9577     (flush _test-output-buffered-file)
 9578     (flush _test-error-buffered-file)
 9579 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9585     # check output
 9586     (check-stream-equal _test-output-stream  ""  "F - test-compare-non-scalar: output should be empty")
 9587 #?     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compare: 'x' is too large to compare"  "F - test-compare-non-scalar: error message")
 9588     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compare: both inouts are in memory"  "F - test-compare-non-scalar: error message")
 9589     # check that stop(1) was called
 9590     (check-ints-equal *(edx+4) 2 "F - test-compare-non-scalar: exit status")
 9591     # don't restore from ebp
 9592     81 0/subop/add %esp 8/imm32
 9593     # . epilogue
 9594     5d/pop-to-ebp
 9595     c3/return
 9596 
 9597 test-compare-with-string-literal:
 9598     # . prologue
 9599     55/push-ebp
 9600     89/<- %ebp 4/r32/esp
 9601     # setup
 9602     (clear-stream _test-input-stream)
 9603     (clear-stream $_test-input-buffered-file->buffer)
 9604     (clear-stream _test-output-stream)
 9605     (clear-stream $_test-output-buffered-file->buffer)
 9606     (clear-stream _test-error-stream)
 9607     (clear-stream $_test-error-buffered-file->buffer)
 9608     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9609     68/push 0/imm32
 9610     68/push 0/imm32
 9611     89/<- %edx 4/r32/esp
 9612     (tailor-exit-descriptor %edx 0x10)
 9613     #
 9614     (write _test-input-stream "fn foo {\n")
 9615     (write _test-input-stream "  var x/eax: (addr array byte) <- copy 0\n")
 9616     (write _test-input-stream "  compare x, \"abc\"\n")
 9617     (write _test-input-stream "}\n")
 9618     # convert
 9619     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9620     # registers except esp clobbered at this point
 9621     # restore ed
 9622     89/<- %edx 4/r32/esp
 9623     (flush _test-output-buffered-file)
 9624     (flush _test-error-buffered-file)
 9625 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9631     # check output
 9632     (check-stream-equal _test-output-stream  ""  "F - test-compare-with-string-literal: output should be empty")
 9633     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compare: string literal \"abc\" is not supported; use the string-equal? function"  "F - test-compare-with-string-literal: error message")
 9634     # check that stop(1) was called
 9635     (check-ints-equal *(edx+4) 2 "F - test-compare-with-string-literal: exit status")
 9636     # don't restore from ebp
 9637     81 0/subop/add %esp 8/imm32
 9638     # . epilogue
 9639     5d/pop-to-ebp
 9640     c3/return
 9641 
 9642 test-address-with-no-inout:
 9643     # . prologue
 9644     55/push-ebp
 9645     89/<- %ebp 4/r32/esp
 9646     # setup
 9647     (clear-stream _test-input-stream)
 9648     (clear-stream $_test-input-buffered-file->buffer)
 9649     (clear-stream _test-output-stream)
 9650     (clear-stream $_test-output-buffered-file->buffer)
 9651     (clear-stream _test-error-stream)
 9652     (clear-stream $_test-error-buffered-file->buffer)
 9653     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9654     68/push 0/imm32
 9655     68/push 0/imm32
 9656     89/<- %edx 4/r32/esp
 9657     (tailor-exit-descriptor %edx 0x10)
 9658     #
 9659     (write _test-input-stream "fn foo {\n")
 9660     (write _test-input-stream "  var x/eax: boolean <- address\n")
 9661     (write _test-input-stream "}\n")
 9662     # convert
 9663     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9664     # registers except esp clobbered at this point
 9665     # restore ed
 9666     89/<- %edx 4/r32/esp
 9667     (flush _test-output-buffered-file)
 9668     (flush _test-error-buffered-file)
 9669 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9675     # check output
 9676     (check-stream-equal _test-output-stream  ""  "F - test-address-with-no-inout: output should be empty")
 9677     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'address' expects an inout"  "F - test-address-with-no-inout: error message")
 9678     # check that stop(1) was called
 9679     (check-ints-equal *(edx+4) 2 "F - test-address-with-no-inout: exit status")
 9680     # don't restore from ebp
 9681     81 0/subop/add %esp 8/imm32
 9682     # . epilogue
 9683     5d/pop-to-ebp
 9684     c3/return
 9685 
 9686 test-address-with-multiple-inouts:
 9687     # . prologue
 9688     55/push-ebp
 9689     89/<- %ebp 4/r32/esp
 9690     # setup
 9691     (clear-stream _test-input-stream)
 9692     (clear-stream $_test-input-buffered-file->buffer)
 9693     (clear-stream _test-output-stream)
 9694     (clear-stream $_test-output-buffered-file->buffer)
 9695     (clear-stream _test-error-stream)
 9696     (clear-stream $_test-error-buffered-file->buffer)
 9697     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9698     68/push 0/imm32
 9699     68/push 0/imm32
 9700     89/<- %edx 4/r32/esp
 9701     (tailor-exit-descriptor %edx 0x10)
 9702     #
 9703     (write _test-input-stream "fn foo {\n")
 9704     (write _test-input-stream "  var x/eax: boolean <- address 0, 0\n")
 9705     (write _test-input-stream "}\n")
 9706     # convert
 9707     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9708     # registers except esp clobbered at this point
 9709     # restore ed
 9710     89/<- %edx 4/r32/esp
 9711     (flush _test-output-buffered-file)
 9712     (flush _test-error-buffered-file)
 9713 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9719     # check output
 9720     (check-stream-equal _test-output-stream  ""  "F - test-address-with-multiple-inouts: output should be empty")
 9721     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'address' must have just one inout"  "F - test-address-with-multiple-inouts: error message")
 9722     # check that stop(1) was called
 9723     (check-ints-equal *(edx+4) 2 "F - test-address-with-multiple-inouts: exit status")
 9724     # don't restore from ebp
 9725     81 0/subop/add %esp 8/imm32
 9726     # . epilogue
 9727     5d/pop-to-ebp
 9728     c3/return
 9729 
 9730 test-address-with-no-output:
 9731     # . prologue
 9732     55/push-ebp
 9733     89/<- %ebp 4/r32/esp
 9734     # setup
 9735     (clear-stream _test-input-stream)
 9736     (clear-stream $_test-input-buffered-file->buffer)
 9737     (clear-stream _test-output-stream)
 9738     (clear-stream $_test-output-buffered-file->buffer)
 9739     (clear-stream _test-error-stream)
 9740     (clear-stream $_test-error-buffered-file->buffer)
 9741     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9742     68/push 0/imm32
 9743     68/push 0/imm32
 9744     89/<- %edx 4/r32/esp
 9745     (tailor-exit-descriptor %edx 0x10)
 9746     #
 9747     (write _test-input-stream "fn foo {\n")
 9748     (write _test-input-stream "  address 0\n")
 9749     (write _test-input-stream "}\n")
 9750     # convert
 9751     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9752     # registers except esp clobbered at this point
 9753     # restore ed
 9754     89/<- %edx 4/r32/esp
 9755     (flush _test-output-buffered-file)
 9756     (flush _test-error-buffered-file)
 9757 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9763     # check output
 9764     (check-stream-equal _test-output-stream  ""  "F - test-address-with-no-output: output should be empty")
 9765     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'address' expects an output"  "F - test-address-with-no-output: error message")
 9766     # check that stop(1) was called
 9767     (check-ints-equal *(edx+4) 2 "F - test-address-with-no-output: exit status")
 9768     # don't restore from ebp
 9769     81 0/subop/add %esp 8/imm32
 9770     # . epilogue
 9771     5d/pop-to-ebp
 9772     c3/return
 9773 
 9774 test-address-with-multiple-outputs:
 9775     # . prologue
 9776     55/push-ebp
 9777     89/<- %ebp 4/r32/esp
 9778     # setup
 9779     (clear-stream _test-input-stream)
 9780     (clear-stream $_test-input-buffered-file->buffer)
 9781     (clear-stream _test-output-stream)
 9782     (clear-stream $_test-output-buffered-file->buffer)
 9783     (clear-stream _test-error-stream)
 9784     (clear-stream $_test-error-buffered-file->buffer)
 9785     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9786     68/push 0/imm32
 9787     68/push 0/imm32
 9788     89/<- %edx 4/r32/esp
 9789     (tailor-exit-descriptor %edx 0x10)
 9790     #
 9791     (write _test-input-stream "fn foo {\n")
 9792     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
 9793     (write _test-input-stream "  var y/ecx: boolean <- copy 0\n")
 9794     (write _test-input-stream "  x, y <- address 0\n")
 9795     (write _test-input-stream "}\n")
 9796     # convert
 9797     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9798     # registers except esp clobbered at this point
 9799     # restore ed
 9800     89/<- %edx 4/r32/esp
 9801     (flush _test-output-buffered-file)
 9802     (flush _test-error-buffered-file)
 9803 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9809     # check output
 9810     (check-stream-equal _test-output-stream  ""  "F - test-address-with-multiple-outputs: output should be empty")
 9811     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'address' must have just one output"  "F - test-address-with-multiple-outputs: error message")
 9812     # check that stop(1) was called
 9813     (check-ints-equal *(edx+4) 2 "F - test-address-with-multiple-outputs: exit status")
 9814     # don't restore from ebp
 9815     81 0/subop/add %esp 8/imm32
 9816     # . epilogue
 9817     5d/pop-to-ebp
 9818     c3/return
 9819 
 9820 # silly but it works
 9821 test-address-of-deref:
 9822     # . prologue
 9823     55/push-ebp
 9824     89/<- %ebp 4/r32/esp
 9825     # setup
 9826     (clear-stream _test-input-stream)
 9827     (clear-stream $_test-input-buffered-file->buffer)
 9828     (clear-stream _test-output-stream)
 9829     (clear-stream $_test-output-buffered-file->buffer)
 9830     #
 9831     (write _test-input-stream "fn foo {\n")
 9832     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
 9833     (write _test-input-stream "  var y/ecx: (addr int) <- address *x\n")
 9834     (write _test-input-stream "}\n")
 9835     # convert
 9836     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 9837     (flush _test-output-buffered-file)
 9838     # no errors
 9839     # . epilogue
 9840     5d/pop-to-ebp
 9841     c3/return
 9842 
 9843 test-address-to-non-register:
 9844     # . prologue
 9845     55/push-ebp
 9846     89/<- %ebp 4/r32/esp
 9847     # setup
 9848     (clear-stream _test-input-stream)
 9849     (clear-stream $_test-input-buffered-file->buffer)
 9850     (clear-stream _test-output-stream)
 9851     (clear-stream $_test-output-buffered-file->buffer)
 9852     (clear-stream _test-error-stream)
 9853     (clear-stream $_test-error-buffered-file->buffer)
 9854     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9855     68/push 0/imm32
 9856     68/push 0/imm32
 9857     89/<- %edx 4/r32/esp
 9858     (tailor-exit-descriptor %edx 0x10)
 9859     #
 9860     (write _test-input-stream "fn foo {\n")
 9861     (write _test-input-stream "  var x: (addr int)\n")
 9862     (write _test-input-stream "  x <- address 0\n")
 9863     (write _test-input-stream "}\n")
 9864     # convert
 9865     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9866     # registers except esp clobbered at this point
 9867     # restore ed
 9868     89/<- %edx 4/r32/esp
 9869     (flush _test-output-buffered-file)
 9870     (flush _test-error-buffered-file)
 9871 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9877     # check output
 9878     (check-stream-equal _test-output-stream  ""  "F - test-address-to-non-register: output should be empty")
 9879     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt address: output 'x' not in a register"  "F - test-address-to-non-register: error message")
 9880     # check that stop(1) was called
 9881     (check-ints-equal *(edx+4) 2 "F - test-address-to-non-register: exit status")
 9882     # don't restore from ebp
 9883     81 0/subop/add %esp 8/imm32
 9884     # . epilogue
 9885     5d/pop-to-ebp
 9886     c3/return
 9887 
 9888 test-address-with-wrong-type:
 9889     # . prologue
 9890     55/push-ebp
 9891     89/<- %ebp 4/r32/esp
 9892     # setup
 9893     (clear-stream _test-input-stream)
 9894     (clear-stream $_test-input-buffered-file->buffer)
 9895     (clear-stream _test-output-stream)
 9896     (clear-stream $_test-output-buffered-file->buffer)
 9897     (clear-stream _test-error-stream)
 9898     (clear-stream $_test-error-buffered-file->buffer)
 9899     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9900     68/push 0/imm32
 9901     68/push 0/imm32
 9902     89/<- %edx 4/r32/esp
 9903     (tailor-exit-descriptor %edx 0x10)
 9904     #
 9905     (write _test-input-stream "fn foo {\n")
 9906     (write _test-input-stream "  var x: int\n")
 9907     (write _test-input-stream "  var y/eax: (addr boolean) <- address x\n")
 9908     (write _test-input-stream "}\n")
 9909     # convert
 9910     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9911     # registers except esp clobbered at this point
 9912     # restore ed
 9913     89/<- %edx 4/r32/esp
 9914     (flush _test-output-buffered-file)
 9915     (flush _test-error-buffered-file)
 9916 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9922     # check output
 9923     (check-stream-equal _test-output-stream  ""  "F - test-address-with-wrong-type: output should be empty")
 9924     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt address: output 'y' cannot hold address of 'x'"  "F - test-address-with-wrong-type: error message")
 9925     # check that stop(1) was called
 9926     (check-ints-equal *(edx+4) 2 "F - test-address-with-wrong-type: exit status")
 9927     # don't restore from ebp
 9928     81 0/subop/add %esp 8/imm32
 9929     # . epilogue
 9930     5d/pop-to-ebp
 9931     c3/return
 9932 
 9933 test-address-with-right-type-for-array:
 9934     # . prologue
 9935     55/push-ebp
 9936     89/<- %ebp 4/r32/esp
 9937     # setup
 9938     (clear-stream _test-input-stream)
 9939     (clear-stream $_test-input-buffered-file->buffer)
 9940     (clear-stream _test-output-stream)
 9941     (clear-stream $_test-output-buffered-file->buffer)
 9942     #
 9943     (write _test-input-stream "fn foo {\n")
 9944     (write _test-input-stream "  var x: (array int 3)\n")
 9945     (write _test-input-stream "  var y/eax: (addr array int) <- address x\n")
 9946     (write _test-input-stream "}\n")
 9947     # convert
 9948     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 9949     (flush _test-output-buffered-file)
 9950     # no errors
 9951     # . epilogue
 9952     89/<- %esp 5/r32/ebp
 9953     5d/pop-to-ebp
 9954     c3/return
 9955 
 9956 test-address-with-right-type-for-stream:
 9957     # . prologue
 9958     55/push-ebp
 9959     89/<- %ebp 4/r32/esp
 9960     # setup
 9961     (clear-stream _test-input-stream)
 9962     (clear-stream $_test-input-buffered-file->buffer)
 9963     (clear-stream _test-output-stream)
 9964     (clear-stream $_test-output-buffered-file->buffer)
 9965     #
 9966     (write _test-input-stream "fn foo {\n")
 9967     (write _test-input-stream "  var x: (stream int 3)\n")
 9968     (write _test-input-stream "  var y/eax: (addr stream int) <- address x\n")
 9969     (write _test-input-stream "}\n")
 9970     # convert
 9971     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 9972     (flush _test-output-buffered-file)
 9973     # no errors
 9974     # . epilogue
 9975     89/<- %esp 5/r32/ebp
 9976     5d/pop-to-ebp
 9977     c3/return
 9978 
 9979 test-get-with-wrong-field:
 9980     # . prologue
 9981     55/push-ebp
 9982     89/<- %ebp 4/r32/esp
 9983     # setup
 9984     (clear-stream _test-input-stream)
 9985     (clear-stream $_test-input-buffered-file->buffer)
 9986     (clear-stream _test-output-stream)
 9987     (clear-stream $_test-output-buffered-file->buffer)
 9988     (clear-stream _test-error-stream)
 9989     (clear-stream $_test-error-buffered-file->buffer)
 9990     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9991     68/push 0/imm32
 9992     68/push 0/imm32
 9993     89/<- %edx 4/r32/esp
 9994     (tailor-exit-descriptor %edx 0x10)
 9995     #
 9996     (write _test-input-stream "fn foo {\n")
 9997     (write _test-input-stream "  var a: t\n")
 9998     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 9999     (write _test-input-stream "}\n")
10000     (write _test-input-stream "type t {\n")
10001     (write _test-input-stream "  x: int\n")
10002     (write _test-input-stream "}\n")
10003     # convert
10004     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10005     # registers except esp clobbered at this point
10006     # restore ed
10007     89/<- %edx 4/r32/esp
10008     (flush _test-output-buffered-file)
10009     (flush _test-error-buffered-file)
10010 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10016     # check output
10017     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-field: output should be empty")
10018     (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")
10019     # check that stop(1) was called
10020     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-field: exit status")
10021     # don't restore from ebp
10022     81 0/subop/add %esp 8/imm32
10023     # . epilogue
10024     5d/pop-to-ebp
10025     c3/return
10026 
10027 test-get-with-wrong-base-type:
10028     # . prologue
10029     55/push-ebp
10030     89/<- %ebp 4/r32/esp
10031     # setup
10032     (clear-stream _test-input-stream)
10033     (clear-stream $_test-input-buffered-file->buffer)
10034     (clear-stream _test-output-stream)
10035     (clear-stream $_test-output-buffered-file->buffer)
10036     (clear-stream _test-error-stream)
10037     (clear-stream $_test-error-buffered-file->buffer)
10038     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10039     68/push 0/imm32
10040     68/push 0/imm32
10041     89/<- %edx 4/r32/esp
10042     (tailor-exit-descriptor %edx 0x10)
10043     #
10044     (write _test-input-stream "fn foo {\n")
10045     (write _test-input-stream "  var a: int\n")
10046     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
10047     (write _test-input-stream "}\n")
10048     # convert
10049     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10050     # registers except esp clobbered at this point
10051     # restore ed
10052     89/<- %edx 4/r32/esp
10053     (flush _test-output-buffered-file)
10054     (flush _test-error-buffered-file)
10055 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10061     # check output
10062     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-base-type: output should be empty")
10063     (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")
10064     # check that stop(1) was called
10065     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-base-type: exit status")
10066     # don't restore from ebp
10067     81 0/subop/add %esp 8/imm32
10068     # . epilogue
10069     5d/pop-to-ebp
10070     c3/return
10071 
10072 test-get-with-wrong-base-type-2:
10073     # . prologue
10074     55/push-ebp
10075     89/<- %ebp 4/r32/esp
10076     # setup
10077     (clear-stream _test-input-stream)
10078     (clear-stream $_test-input-buffered-file->buffer)
10079     (clear-stream _test-output-stream)
10080     (clear-stream $_test-output-buffered-file->buffer)
10081     (clear-stream _test-error-stream)
10082     (clear-stream $_test-error-buffered-file->buffer)
10083     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10084     68/push 0/imm32
10085     68/push 0/imm32
10086     89/<- %edx 4/r32/esp
10087     (tailor-exit-descriptor %edx 0x10)
10088     #
10089     (write _test-input-stream "fn foo {\n")
10090     (write _test-input-stream "  var a: (addr t)\n")
10091     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
10092     (write _test-input-stream "}\n")
10093     (write _test-input-stream "type t {\n")
10094     (write _test-input-stream "  x: int\n")
10095     (write _test-input-stream "}\n")
10096     # convert
10097     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10098     # registers except esp clobbered at this point
10099     # restore ed
10100     89/<- %edx 4/r32/esp
10101     (flush _test-output-buffered-file)
10102     (flush _test-error-buffered-file)
10103 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10109     # check output
10110     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-base-type-2: output should be empty")
10111     (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")
10112     # check that stop(1) was called
10113     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-base-type-2: exit status")
10114     # don't restore from ebp
10115     81 0/subop/add %esp 8/imm32
10116     # . epilogue
10117     5d/pop-to-ebp
10118     c3/return
10119 
10120 test-get-with-wrong-base-type-3:
10121     # . prologue
10122     55/push-ebp
10123     89/<- %ebp 4/r32/esp
10124     # setup
10125     (clear-stream _test-input-stream)
10126     (clear-stream $_test-input-buffered-file->buffer)
10127     (clear-stream _test-output-stream)
10128     (clear-stream $_test-output-buffered-file->buffer)
10129     (clear-stream _test-error-stream)
10130     (clear-stream $_test-error-buffered-file->buffer)
10131     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10132     68/push 0/imm32
10133     68/push 0/imm32
10134     89/<- %edx 4/r32/esp
10135     (tailor-exit-descriptor %edx 0x10)
10136     #
10137     (write _test-input-stream "fn foo {\n")
10138     (write _test-input-stream "  var a: (handle int)\n")
10139     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
10140     (write _test-input-stream "}\n")
10141     # convert
10142     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10143     # registers except esp clobbered at this point
10144     # restore ed
10145     89/<- %edx 4/r32/esp
10146     (flush _test-output-buffered-file)
10147     (flush _test-error-buffered-file)
10148 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10154     # check output
10155     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-base-type-3: output should be empty")
10156     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt get: var 'a' must have a 'type' definition"  "F - test-get-with-wrong-base-type-3: error message")
10157     # check that stop(1) was called
10158     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-base-type-3: exit status")
10159     # don't restore from ebp
10160     81 0/subop/add %esp 8/imm32
10161     # . epilogue
10162     5d/pop-to-ebp
10163     c3/return
10164 
10165 test-get-with-wrong-offset-type:
10166     # . prologue
10167     55/push-ebp
10168     89/<- %ebp 4/r32/esp
10169     # setup
10170     (clear-stream _test-input-stream)
10171     (clear-stream $_test-input-buffered-file->buffer)
10172     (clear-stream _test-output-stream)
10173     (clear-stream $_test-output-buffered-file->buffer)
10174     (clear-stream _test-error-stream)
10175     (clear-stream $_test-error-buffered-file->buffer)
10176     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10177     68/push 0/imm32
10178     68/push 0/imm32
10179     89/<- %edx 4/r32/esp
10180     (tailor-exit-descriptor %edx 0x10)
10181     #
10182     (write _test-input-stream "fn foo {\n")
10183     (write _test-input-stream "  var a: t\n")
10184     (write _test-input-stream "  var b: int\n")
10185     (write _test-input-stream "  var c/ecx: (addr int) <- get a, b\n")
10186     (write _test-input-stream "}\n")
10187     (write _test-input-stream "type t {\n")
10188     (write _test-input-stream "  x: int\n")
10189     (write _test-input-stream "}\n")
10190     # convert
10191     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10192     # registers except esp clobbered at this point
10193     # restore ed
10194     89/<- %edx 4/r32/esp
10195     (flush _test-output-buffered-file)
10196     (flush _test-error-buffered-file)
10197 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10203     # check output
10204     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-offset-type: output should be empty")
10205     (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")
10206     # check that stop(1) was called
10207     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-offset-type: exit status")
10208     # don't restore from ebp
10209     81 0/subop/add %esp 8/imm32
10210     # . epilogue
10211     5d/pop-to-ebp
10212     c3/return
10213 
10214 test-get-with-wrong-output-type:
10215     # . prologue
10216     55/push-ebp
10217     89/<- %ebp 4/r32/esp
10218     # setup
10219     (clear-stream _test-input-stream)
10220     (clear-stream $_test-input-buffered-file->buffer)
10221     (clear-stream _test-output-stream)
10222     (clear-stream $_test-output-buffered-file->buffer)
10223     (clear-stream _test-error-stream)
10224     (clear-stream $_test-error-buffered-file->buffer)
10225     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10226     68/push 0/imm32
10227     68/push 0/imm32
10228     89/<- %edx 4/r32/esp
10229     (tailor-exit-descriptor %edx 0x10)
10230     #
10231     (write _test-input-stream "fn foo {\n")
10232     (write _test-input-stream "  var a: t\n")
10233     (write _test-input-stream "  var c: (addr int)\n")
10234     (write _test-input-stream "  c <- get a, x\n")
10235     (write _test-input-stream "}\n")
10236     (write _test-input-stream "type t {\n")
10237     (write _test-input-stream "  x: int\n")
10238     (write _test-input-stream "}\n")
10239     # convert
10240     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10241     # registers except esp clobbered at this point
10242     # restore ed
10243     89/<- %edx 4/r32/esp
10244     (flush _test-output-buffered-file)
10245     (flush _test-error-buffered-file)
10246 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10252     # check output
10253     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type: output should be empty")
10254     (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")
10255     # check that stop(1) was called
10256     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type: exit status")
10257     # don't restore from ebp
10258     81 0/subop/add %esp 8/imm32
10259     # . epilogue
10260     5d/pop-to-ebp
10261     c3/return
10262 
10263 test-get-with-wrong-output-type-2:
10264     # . prologue
10265     55/push-ebp
10266     89/<- %ebp 4/r32/esp
10267     # setup
10268     (clear-stream _test-input-stream)
10269     (clear-stream $_test-input-buffered-file->buffer)
10270     (clear-stream _test-output-stream)
10271     (clear-stream $_test-output-buffered-file->buffer)
10272     (clear-stream _test-error-stream)
10273     (clear-stream $_test-error-buffered-file->buffer)
10274     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10275     68/push 0/imm32
10276     68/push 0/imm32
10277     89/<- %edx 4/r32/esp
10278     (tailor-exit-descriptor %edx 0x10)
10279     #
10280     (write _test-input-stream "fn foo {\n")
10281     (write _test-input-stream "  var a: t\n")
10282     (write _test-input-stream "  var c/ecx: int <- get a, x\n")
10283     (write _test-input-stream "}\n")
10284     (write _test-input-stream "type t {\n")
10285     (write _test-input-stream "  x: int\n")
10286     (write _test-input-stream "}\n")
10287     # convert
10288     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10289     # registers except esp clobbered at this point
10290     # restore ed
10291     89/<- %edx 4/r32/esp
10292     (flush _test-output-buffered-file)
10293     (flush _test-error-buffered-file)
10294 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10300     # check output
10301     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type-2: output should be empty")
10302     (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")
10303     # check that stop(1) was called
10304     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type-2: exit status")
10305     # don't restore from ebp
10306     81 0/subop/add %esp 8/imm32
10307     # . epilogue
10308     5d/pop-to-ebp
10309     c3/return
10310 
10311 test-get-with-wrong-output-type-3:
10312     # . prologue
10313     55/push-ebp
10314     89/<- %ebp 4/r32/esp
10315     # setup
10316     (clear-stream _test-input-stream)
10317     (clear-stream $_test-input-buffered-file->buffer)
10318     (clear-stream _test-output-stream)
10319     (clear-stream $_test-output-buffered-file->buffer)
10320     (clear-stream _test-error-stream)
10321     (clear-stream $_test-error-buffered-file->buffer)
10322     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10323     68/push 0/imm32
10324     68/push 0/imm32
10325     89/<- %edx 4/r32/esp
10326     (tailor-exit-descriptor %edx 0x10)
10327     #
10328     (write _test-input-stream "fn foo {\n")
10329     (write _test-input-stream "  var a: t\n")
10330     (write _test-input-stream "  var c/ecx: (array int) <- get a, x\n")
10331     (write _test-input-stream "}\n")
10332     (write _test-input-stream "type t {\n")
10333     (write _test-input-stream "  x: int\n")
10334     (write _test-input-stream "}\n")
10335     # convert
10336     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10337     # registers except esp clobbered at this point
10338     # restore ed
10339     89/<- %edx 4/r32/esp
10340     (flush _test-output-buffered-file)
10341     (flush _test-error-buffered-file)
10342 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10348     # check output
10349     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type-3: output should be empty")
10350     (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")
10351     # check that stop(1) was called
10352     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type-3: exit status")
10353     # don't restore from ebp
10354     81 0/subop/add %esp 8/imm32
10355     # . epilogue
10356     5d/pop-to-ebp
10357     c3/return
10358 
10359 test-get-with-wrong-output-type-4:
10360     # . prologue
10361     55/push-ebp
10362     89/<- %ebp 4/r32/esp
10363     # setup
10364     (clear-stream _test-input-stream)
10365     (clear-stream $_test-input-buffered-file->buffer)
10366     (clear-stream _test-output-stream)
10367     (clear-stream $_test-output-buffered-file->buffer)
10368     (clear-stream _test-error-stream)
10369     (clear-stream $_test-error-buffered-file->buffer)
10370     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10371     68/push 0/imm32
10372     68/push 0/imm32
10373     89/<- %edx 4/r32/esp
10374     (tailor-exit-descriptor %edx 0x10)
10375     #
10376     (write _test-input-stream "fn foo {\n")
10377     (write _test-input-stream "  var a: t\n")
10378     (write _test-input-stream "  var c/ecx: (addr boolean) <- get a, x\n")
10379     (write _test-input-stream "}\n")
10380     (write _test-input-stream "type t {\n")
10381     (write _test-input-stream "  x: int\n")
10382     (write _test-input-stream "}\n")
10383     # convert
10384     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10385     # registers except esp clobbered at this point
10386     # restore ed
10387     89/<- %edx 4/r32/esp
10388     (flush _test-output-buffered-file)
10389     (flush _test-error-buffered-file)
10390 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10396     # check output
10397     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type-4: output should be empty")
10398     (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")
10399     # check that stop(1) was called
10400     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type-4: exit status")
10401     # don't restore from ebp
10402     81 0/subop/add %esp 8/imm32
10403     # . epilogue
10404     5d/pop-to-ebp
10405     c3/return
10406 
10407 test-get-with-wrong-output-type-5:
10408     # . prologue
10409     55/push-ebp
10410     89/<- %ebp 4/r32/esp
10411     # setup
10412     (clear-stream _test-input-stream)
10413     (clear-stream $_test-input-buffered-file->buffer)
10414     (clear-stream _test-output-stream)
10415     (clear-stream $_test-output-buffered-file->buffer)
10416     #
10417     (write _test-input-stream "fn foo {\n")
10418     (write _test-input-stream "  var a: t\n")
10419     (write _test-input-stream "  var c/ecx: (addr handle int) <- get a, x\n")
10420     (write _test-input-stream "}\n")
10421     (write _test-input-stream "type t {\n")
10422     (write _test-input-stream "  x: (handle int)\n")
10423     (write _test-input-stream "}\n")
10424     # convert
10425     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
10426     (flush _test-output-buffered-file)
10427     # no errors
10428     # . epilogue
10429     89/<- %esp 5/r32/ebp
10430     5d/pop-to-ebp
10431     c3/return
10432 
10433 test-get-with-too-few-inouts:
10434     # . prologue
10435     55/push-ebp
10436     89/<- %ebp 4/r32/esp
10437     # setup
10438     (clear-stream _test-input-stream)
10439     (clear-stream $_test-input-buffered-file->buffer)
10440     (clear-stream _test-output-stream)
10441     (clear-stream $_test-output-buffered-file->buffer)
10442     (clear-stream _test-error-stream)
10443     (clear-stream $_test-error-buffered-file->buffer)
10444     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10445     68/push 0/imm32
10446     68/push 0/imm32
10447     89/<- %edx 4/r32/esp
10448     (tailor-exit-descriptor %edx 0x10)
10449     #
10450     (write _test-input-stream "fn foo {\n")
10451     (write _test-input-stream "  var a: t\n")
10452     (write _test-input-stream "  var c/ecx: (addr int) <- get a\n")
10453     (write _test-input-stream "}\n")
10454     (write _test-input-stream "type t {\n")
10455     (write _test-input-stream "  x: int\n")
10456     (write _test-input-stream "}\n")
10457     # convert
10458     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10459     # registers except esp clobbered at this point
10460     # restore ed
10461     89/<- %edx 4/r32/esp
10462     (flush _test-output-buffered-file)
10463     (flush _test-error-buffered-file)
10464 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10470     # check output
10471     (check-stream-equal _test-output-stream  ""  "F - test-get-with-too-few-inouts: output should be empty")
10472     (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")
10473     # check that stop(1) was called
10474     (check-ints-equal *(edx+4) 2 "F - test-get-with-too-few-inouts: exit status")
10475     # don't restore from ebp
10476     81 0/subop/add %esp 8/imm32
10477     # . epilogue
10478     5d/pop-to-ebp
10479     c3/return
10480 
10481 test-get-with-too-many-inouts:
10482     # . prologue
10483     55/push-ebp
10484     89/<- %ebp 4/r32/esp
10485     # setup
10486     (clear-stream _test-input-stream)
10487     (clear-stream $_test-input-buffered-file->buffer)
10488     (clear-stream _test-output-stream)
10489     (clear-stream $_test-output-buffered-file->buffer)
10490     (clear-stream _test-error-stream)
10491     (clear-stream $_test-error-buffered-file->buffer)
10492     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10493     68/push 0/imm32
10494     68/push 0/imm32
10495     89/<- %edx 4/r32/esp
10496     (tailor-exit-descriptor %edx 0x10)
10497     #
10498     (write _test-input-stream "fn foo {\n")
10499     (write _test-input-stream "  var a: t\n")
10500     (write _test-input-stream "  var c/ecx: (addr int) <- get a, x, 0\n")
10501     (write _test-input-stream "}\n")
10502     (write _test-input-stream "type t {\n")
10503     (write _test-input-stream "  x: int\n")
10504     (write _test-input-stream "}\n")
10505     # convert
10506     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10507     # registers except esp clobbered at this point
10508     # restore ed
10509     89/<- %edx 4/r32/esp
10510     (flush _test-output-buffered-file)
10511     (flush _test-error-buffered-file)
10512 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10518     # check output
10519     (check-stream-equal _test-output-stream  ""  "F - test-get-with-too-many-inouts: output should be empty")
10520     (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")
10521     # check that stop(1) was called
10522     (check-ints-equal *(edx+4) 2 "F - test-get-with-too-many-inouts: exit status")
10523     # don't restore from ebp
10524     81 0/subop/add %esp 8/imm32
10525     # . epilogue
10526     5d/pop-to-ebp
10527     c3/return
10528 
10529 test-get-with-no-output:
10530     # . prologue
10531     55/push-ebp
10532     89/<- %ebp 4/r32/esp
10533     # setup
10534     (clear-stream _test-input-stream)
10535     (clear-stream $_test-input-buffered-file->buffer)
10536     (clear-stream _test-output-stream)
10537     (clear-stream $_test-output-buffered-file->buffer)
10538     (clear-stream _test-error-stream)
10539     (clear-stream $_test-error-buffered-file->buffer)
10540     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10541     68/push 0/imm32
10542     68/push 0/imm32
10543     89/<- %edx 4/r32/esp
10544     (tailor-exit-descriptor %edx 0x10)
10545     #
10546     (write _test-input-stream "fn foo {\n")
10547     (write _test-input-stream "  var a: t\n")
10548     (write _test-input-stream "  get a, x\n")
10549     (write _test-input-stream "}\n")
10550     (write _test-input-stream "type t {\n")
10551     (write _test-input-stream "  x: int\n")
10552     (write _test-input-stream "}\n")
10553     # convert
10554     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10555     # registers except esp clobbered at this point
10556     # restore ed
10557     89/<- %edx 4/r32/esp
10558     (flush _test-output-buffered-file)
10559     (flush _test-error-buffered-file)
10560 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10566     # check output
10567     (check-stream-equal _test-output-stream  ""  "F - test-get-with-no-output: output should be empty")
10568     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt get: must have an output"  "F - test-get-with-no-output: error message")
10569     # check that stop(1) was called
10570     (check-ints-equal *(edx+4) 2 "F - test-get-with-no-output: exit status")
10571     # don't restore from ebp
10572     81 0/subop/add %esp 8/imm32
10573     # . epilogue
10574     5d/pop-to-ebp
10575     c3/return
10576 
10577 test-get-with-too-many-outputs:
10578     # . prologue
10579     55/push-ebp
10580     89/<- %ebp 4/r32/esp
10581     # setup
10582     (clear-stream _test-input-stream)
10583     (clear-stream $_test-input-buffered-file->buffer)
10584     (clear-stream _test-output-stream)
10585     (clear-stream $_test-output-buffered-file->buffer)
10586     (clear-stream _test-error-stream)
10587     (clear-stream $_test-error-buffered-file->buffer)
10588     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10589     68/push 0/imm32
10590     68/push 0/imm32
10591     89/<- %edx 4/r32/esp
10592     (tailor-exit-descriptor %edx 0x10)
10593     #
10594     (write _test-input-stream "fn foo {\n")
10595     (write _test-input-stream "  var a: t\n")
10596     (write _test-input-stream "  var b: int\n")
10597     (write _test-input-stream "  var c/eax: (addr int) <- copy 0\n")
10598     (write _test-input-stream "  c, b <- get a, x\n")
10599     (write _test-input-stream "}\n")
10600     (write _test-input-stream "type t {\n")
10601     (write _test-input-stream "  x: int\n")
10602     (write _test-input-stream "}\n")
10603     # convert
10604     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10605     # registers except esp clobbered at this point
10606     # restore ed
10607     89/<- %edx 4/r32/esp
10608     (flush _test-output-buffered-file)
10609     (flush _test-error-buffered-file)
10610 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10616     # check output
10617     (check-stream-equal _test-output-stream  ""  "F - test-get-with-too-many-outputs: output should be empty")
10618     (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")
10619     # check that stop(1) was called
10620     (check-ints-equal *(edx+4) 2 "F - test-get-with-too-many-outputs: exit status")
10621     # don't restore from ebp
10622     81 0/subop/add %esp 8/imm32
10623     # . epilogue
10624     5d/pop-to-ebp
10625     c3/return
10626 
10627 test-convert-array-of-user-defined-types:
10628     # . prologue
10629     55/push-ebp
10630     89/<- %ebp 4/r32/esp
10631     # setup
10632     (clear-stream _test-input-stream)
10633     (clear-stream $_test-input-buffered-file->buffer)
10634     (clear-stream _test-output-stream)
10635     (clear-stream $_test-output-buffered-file->buffer)
10636     #
10637     (write _test-input-stream "type t {\n")  # each t is 8 bytes, which is a power of 2
10638     (write _test-input-stream "  x: int\n")
10639     (write _test-input-stream "  y: int\n")
10640     (write _test-input-stream "}\n")
10641     (write _test-input-stream "fn foo {\n")
10642     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
10643     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
10644     (write _test-input-stream "  var x/eax: (addr t) <- index arr, idx\n")
10645     (write _test-input-stream "}\n")
10646     # convert
10647     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
10648     (flush _test-output-buffered-file)
10649 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
10655     # check output
10656     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-array-of-user-defined-types/0")
10657     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-array-of-user-defined-types/1")
10658     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-array-of-user-defined-types/2")
10659     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-array-of-user-defined-types/3")
10660     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-array-of-user-defined-types/4")
10661     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-array-of-user-defined-types/5")
10662     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-array-of-user-defined-types/6")
10663     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-array-of-user-defined-types/7")
10664     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-array-of-user-defined-types/8")
10665     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-array-of-user-defined-types/9")
10666     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds %ecx 0x00000008 *eax \"foo\" \"arr\")"  "F - test-convert-array-of-user-defined-types/10")
10667     (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")
10668     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-array-of-user-defined-types/12")
10669     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-array-of-user-defined-types/13")
10670     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-array-of-user-defined-types/14")
10671     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-array-of-user-defined-types/15")
10672     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-array-of-user-defined-types/16")
10673     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-array-of-user-defined-types/17")
10674     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-array-of-user-defined-types/18")
10675     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-array-of-user-defined-types/19")
10676     # . epilogue
10677     89/<- %esp 5/r32/ebp
10678     5d/pop-to-ebp
10679     c3/return
10680 
10681 test-convert-length-of-array-of-user-defined-types-to-eax:
10682     # . prologue
10683     55/push-ebp
10684     89/<- %ebp 4/r32/esp
10685     # setup
10686     (clear-stream _test-input-stream)
10687     (clear-stream $_test-input-buffered-file->buffer)
10688     (clear-stream _test-output-stream)
10689     (clear-stream $_test-output-buffered-file->buffer)
10690     #
10691     (write _test-input-stream "type t {\n")  # size = 12, which is not a power of 2
10692     (write _test-input-stream "  x: int\n")
10693     (write _test-input-stream "  y: int\n")
10694     (write _test-input-stream "  z: int\n")
10695     (write _test-input-stream "}\n")
10696     (write _test-input-stream "fn foo {\n")
10697     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
10698     (write _test-input-stream "  var x/eax: int <- length arr\n")
10699     (write _test-input-stream "}\n")
10700     # convert
10701     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
10702     (flush _test-output-buffered-file)
10703 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
10709     # check output
10710     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types-to-eax/0")
10711     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types-to-eax/1")
10712     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types-to-eax/2")
10713     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array-of-user-defined-types-to-eax/3")
10714     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types-to-eax/4")
10715     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types-to-eax/5")
10716     # var arr
10717     (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")
10718     (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")
10719     # length instruction
10720     (check-next-stream-line-equal _test-output-stream "    51/push-ecx"         "F - test-convert-length-of-array-of-user-defined-types-to-eax/8")
10721     (check-next-stream-line-equal _test-output-stream "    52/push-edx"         "F - test-convert-length-of-array-of-user-defined-types-to-eax/9")
10722     (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")
10723     (check-next-stream-line-equal _test-output-stream "    31/xor %edx 2/r32/edx"  "F - test-convert-length-of-array-of-user-defined-types-to-eax/11")
10724     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0x0000000c/imm32"  "F - test-convert-length-of-array-of-user-defined-types-to-eax/12")
10725     (check-next-stream-line-equal _test-output-stream "    f7 7/subop/idiv-eax-edx-by %ecx"  "F - test-convert-length-of-array-of-user-defined-types-to-eax/13")
10726     (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")
10727     (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")
10728     # reclaim arr
10729     (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")
10730     #
10731     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types-to-eax/17")
10732     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types-to-eax/18")
10733     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types-to-eax/19")
10734     (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")
10735     (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")
10736     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types-to-eax/22")
10737     # . epilogue
10738     89/<- %esp 5/r32/ebp
10739     5d/pop-to-ebp
10740     c3/return
10741 
10742 test-convert-length-of-array-of-user-defined-types-to-ecx:
10743     # . prologue
10744     55/push-ebp
10745     89/<- %ebp 4/r32/esp
10746     # setup
10747     (clear-stream _test-input-stream)
10748     (clear-stream $_test-input-buffered-file->buffer)
10749     (clear-stream _test-output-stream)
10750     (clear-stream $_test-output-buffered-file->buffer)
10751     #
10752     (write _test-input-stream "type t {\n")  # size = 12, which is not a power of 2
10753     (write _test-input-stream "  x: int\n")
10754     (write _test-input-stream "  y: int\n")
10755     (write _test-input-stream "  z: int\n")
10756     (write _test-input-stream "}\n")
10757     (write _test-input-stream "fn foo {\n")
10758     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
10759     (write _test-input-stream "  var x/ecx: int <- length arr\n")
10760     (write _test-input-stream "}\n")
10761     # convert
10762     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
10763     (flush _test-output-buffered-file)
10764 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
10770     # check output
10771     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types-to-ecx/0")
10772     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types-to-ecx/1")
10773     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types-to-ecx/2")
10774     (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")
10775     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types-to-ecx/4")
10776     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types-to-ecx/5")
10777     # var a
10778     (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")
10779     (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")
10780     # var x
10781     (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")
10782     # length instruction
10783     (check-next-stream-line-equal _test-output-stream "    50/push-eax"         "F - test-convert-length-of-array-of-user-defined-types-to-ecx/9")
10784     (check-next-stream-line-equal _test-output-stream "    52/push-edx"         "F - test-convert-length-of-array-of-user-defined-types-to-ecx/10")
10785     (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")
10786     (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")
10787     (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")
10788     (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")
10789     (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")
10790     (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")
10791     (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")
10792     # reclaim x
10793     (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")
10794     # reclaim a
10795     (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")
10796     #
10797     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types-to-ecx/20")
10798     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types-to-ecx/21")
10799     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types-to-ecx/22")
10800     (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")
10801     (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")
10802     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types-to-ecx/25")
10803     # . epilogue
10804     89/<- %esp 5/r32/ebp
10805     5d/pop-to-ebp
10806     c3/return
10807 
10808 test-convert-length-of-array-of-user-defined-types-to-edx:
10809     # . prologue
10810     55/push-ebp
10811     89/<- %ebp 4/r32/esp
10812     # setup
10813     (clear-stream _test-input-stream)
10814     (clear-stream $_test-input-buffered-file->buffer)
10815     (clear-stream _test-output-stream)
10816     (clear-stream $_test-output-buffered-file->buffer)
10817     #
10818     (write _test-input-stream "type t {\n")  # size = 12, which is not a power of 2
10819     (write _test-input-stream "  x: int\n")
10820     (write _test-input-stream "  y: int\n")
10821     (write _test-input-stream "  z: int\n")
10822     (write _test-input-stream "}\n")
10823     (write _test-input-stream "fn foo {\n")
10824     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
10825     (write _test-input-stream "  var x/edx: int <- length arr\n")
10826     (write _test-input-stream "}\n")
10827     # convert
10828     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
10829     (flush _test-output-buffered-file)
10830 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
10836     # check output
10837     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types-to-edx/0")
10838     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types-to-edx/1")
10839     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types-to-edx/2")
10840     (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")
10841     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types-to-edx/4")
10842     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types-to-edx/5")
10843     # var a
10844     (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")
10845     (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")
10846     # var x
10847     (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")
10848     # length instruction
10849     (check-next-stream-line-equal _test-output-stream "    50/push-eax"         "F - test-convert-length-of-array-of-user-defined-types-to-edx/9")
10850     (check-next-stream-line-equal _test-output-stream "    51/push-ecx"         "F - test-convert-length-of-array-of-user-defined-types-to-edx/10")
10851     (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")
10852     (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")
10853     (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")
10854     (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")
10855     (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")
10856     (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")
10857     (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")
10858     # reclaim x
10859     (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")
10860     # reclaim a
10861     (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")
10862     #
10863     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types-to-edx/20")
10864     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types-to-edx/21")
10865     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types-to-edx/22")
10866     (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")
10867     (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")
10868     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types-to-edx/25")
10869     # . epilogue
10870     89/<- %esp 5/r32/ebp
10871     5d/pop-to-ebp
10872     c3/return
10873 
10874 test-convert-length-of-array-of-user-defined-types:
10875     # . prologue
10876     55/push-ebp
10877     89/<- %ebp 4/r32/esp
10878     # setup
10879     (clear-stream _test-input-stream)
10880     (clear-stream $_test-input-buffered-file->buffer)
10881     (clear-stream _test-output-stream)
10882     (clear-stream $_test-output-buffered-file->buffer)
10883     #
10884     (write _test-input-stream "type t {\n")  # each t is 8 bytes, which is a power of 2
10885     (write _test-input-stream "  x: int\n")
10886     (write _test-input-stream "  y: int\n")
10887     (write _test-input-stream "  z: int\n")
10888     (write _test-input-stream "}\n")
10889     (write _test-input-stream "fn foo {\n")
10890     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
10891     (write _test-input-stream "  var x/ebx: int <- length arr\n")
10892     (write _test-input-stream "}\n")
10893     # convert
10894     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
10895     (flush _test-output-buffered-file)
10896 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
10902     # check output
10903     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types/0")
10904     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types/1")
10905     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types/2")
10906     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array-of-user-defined-types/3")
10907     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types/4")
10908     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types/5")
10909     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array-of-user-defined-types/6")
10910     (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")
10911     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ebx"  "F - test-convert-length-of-array-of-user-defined-types/8")
10912     (check-next-stream-line-equal _test-output-stream "    50/push-eax"         "F - test-convert-length-of-array-of-user-defined-types/9")
10913     (check-next-stream-line-equal _test-output-stream "    51/push-ecx"         "F - test-convert-length-of-array-of-user-defined-types/10")
10914     (check-next-stream-line-equal _test-output-stream "    52/push-edx"         "F - test-convert-length-of-array-of-user-defined-types/11")
10915     (check-next-stream-line-equal _test-output-stream "    8b/-> *eax 0x00000000/r32"  "F - test-convert-length-of-array-of-user-defined-types/12")
10916     (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")
10917     (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")
10918     (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")
10919     (check-next-stream-line-equal _test-output-stream "    89/<- %ebx 0/r32/eax"  "F - test-convert-length-of-array-of-user-defined-types/16")
10920     (check-next-stream-line-equal _test-output-stream "    5a/pop-to-edx"       "F - test-convert-length-of-array-of-user-defined-types/17")
10921     (check-next-stream-line-equal _test-output-stream "    59/pop-to-ecx"       "F - test-convert-length-of-array-of-user-defined-types/18")
10922     (check-next-stream-line-equal _test-output-stream "    58/pop-to-eax"       "F - test-convert-length-of-array-of-user-defined-types/19")
10923     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ebx"  "F - test-convert-length-of-array-of-user-defined-types/20")
10924     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array-of-user-defined-types/21")
10925     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types/22")
10926     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types/23")
10927     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types/24")
10928     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array-of-user-defined-types/25")
10929     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array-of-user-defined-types/26")
10930     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types/27")
10931     # . epilogue
10932     89/<- %esp 5/r32/ebp
10933     5d/pop-to-ebp
10934     c3/return
10935 
10936 test-index-with-non-array-atom-base-type:
10937     # . prologue
10938     55/push-ebp
10939     89/<- %ebp 4/r32/esp
10940     # setup
10941     (clear-stream _test-input-stream)
10942     (clear-stream $_test-input-buffered-file->buffer)
10943     (clear-stream _test-output-stream)
10944     (clear-stream $_test-output-buffered-file->buffer)
10945     (clear-stream _test-error-stream)
10946     (clear-stream $_test-error-buffered-file->buffer)
10947     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10948     68/push 0/imm32
10949     68/push 0/imm32
10950     89/<- %edx 4/r32/esp
10951     (tailor-exit-descriptor %edx 0x10)
10952     #
10953     (write _test-input-stream "fn foo {\n")
10954     (write _test-input-stream "  var a: int\n")
10955     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
10956     (write _test-input-stream "}\n")
10957     # convert
10958     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10959     # registers except esp clobbered at this point
10960     # restore ed
10961     89/<- %edx 4/r32/esp
10962     (flush _test-output-buffered-file)
10963     (flush _test-error-buffered-file)
10964 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10970     # check output
10971     (check-stream-equal _test-output-stream  ""  "F - test-index-with-non-array-atom-base-type: output should be empty")
10972     (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")
10973     # check that stop(1) was called
10974     (check-ints-equal *(edx+4) 2 "F - test-index-with-non-array-atom-base-type: exit status")
10975     # don't restore from ebp
10976     81 0/subop/add %esp 8/imm32
10977     # . epilogue
10978     5d/pop-to-ebp
10979     c3/return
10980 
10981 test-index-with-non-array-compound-base-type:
10982     # . prologue
10983     55/push-ebp
10984     89/<- %ebp 4/r32/esp
10985     # setup
10986     (clear-stream _test-input-stream)
10987     (clear-stream $_test-input-buffered-file->buffer)
10988     (clear-stream _test-output-stream)
10989     (clear-stream $_test-output-buffered-file->buffer)
10990     (clear-stream _test-error-stream)
10991     (clear-stream $_test-error-buffered-file->buffer)
10992     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10993     68/push 0/imm32
10994     68/push 0/imm32
10995     89/<- %edx 4/r32/esp
10996     (tailor-exit-descriptor %edx 0x10)
10997     #
10998     (write _test-input-stream "fn foo {\n")
10999     (write _test-input-stream "  var a: (handle int)\n")
11000     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
11001     (write _test-input-stream "}\n")
11002     # convert
11003     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11004     # registers except esp clobbered at this point
11005     # restore ed
11006     89/<- %edx 4/r32/esp
11007     (flush _test-output-buffered-file)
11008     (flush _test-error-buffered-file)
11009 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11015     # check output
11016     (check-stream-equal _test-output-stream  ""  "F - test-index-with-non-array-compound-base-type: output should be empty")
11017     (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")
11018     # check that stop(1) was called
11019     (check-ints-equal *(edx+4) 2 "F - test-index-with-non-array-compound-base-type: exit status")
11020     # don't restore from ebp
11021     81 0/subop/add %esp 8/imm32
11022     # . epilogue
11023     5d/pop-to-ebp
11024     c3/return
11025 
11026 test-index-with-non-array-compound-base-type-2:
11027     # . prologue
11028     55/push-ebp
11029     89/<- %ebp 4/r32/esp
11030     # setup
11031     (clear-stream _test-input-stream)
11032     (clear-stream $_test-input-buffered-file->buffer)
11033     (clear-stream _test-output-stream)
11034     (clear-stream $_test-output-buffered-file->buffer)
11035     (clear-stream _test-error-stream)
11036     (clear-stream $_test-error-buffered-file->buffer)
11037     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11038     68/push 0/imm32
11039     68/push 0/imm32
11040     89/<- %edx 4/r32/esp
11041     (tailor-exit-descriptor %edx 0x10)
11042     #
11043     (write _test-input-stream "fn foo {\n")
11044     (write _test-input-stream "  var a: (addr int)\n")
11045     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
11046     (write _test-input-stream "}\n")
11047     # convert
11048     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11049     # registers except esp clobbered at this point
11050     # restore ed
11051     89/<- %edx 4/r32/esp
11052     (flush _test-output-buffered-file)
11053     (flush _test-error-buffered-file)
11054 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11060     # check output
11061     (check-stream-equal _test-output-stream  ""  "F - test-index-with-non-array-compound-base-type-2: output should be empty")
11062     (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")
11063     # check that stop(1) was called
11064     (check-ints-equal *(edx+4) 2 "F - test-index-with-non-array-compound-base-type-2: exit status")
11065     # don't restore from ebp
11066     81 0/subop/add %esp 8/imm32
11067     # . epilogue
11068     5d/pop-to-ebp
11069     c3/return
11070 
11071 test-index-with-array-atom-base-type:
11072     # . prologue
11073     55/push-ebp
11074     89/<- %ebp 4/r32/esp
11075     # setup
11076     (clear-stream _test-input-stream)
11077     (clear-stream $_test-input-buffered-file->buffer)
11078     (clear-stream _test-output-stream)
11079     (clear-stream $_test-output-buffered-file->buffer)
11080     (clear-stream _test-error-stream)
11081     (clear-stream $_test-error-buffered-file->buffer)
11082     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11083     68/push 0/imm32
11084     68/push 0/imm32
11085     89/<- %edx 4/r32/esp
11086     (tailor-exit-descriptor %edx 0x10)
11087     #
11088     (write _test-input-stream "fn foo {\n")
11089     (write _test-input-stream "  var a: array\n")
11090     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
11091     (write _test-input-stream "}\n")
11092     # convert
11093     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11094     # registers except esp clobbered at this point
11095     # restore ed
11096     89/<- %edx 4/r32/esp
11097     (flush _test-output-buffered-file)
11098     (flush _test-error-buffered-file)
11099 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11105     # check output
11106     (check-stream-equal _test-output-stream  ""  "F - test-index-with-array-atom-base-type: output should be empty")
11107     (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")
11108     # check that stop(1) was called
11109     (check-ints-equal *(edx+4) 2 "F - test-index-with-array-atom-base-type: exit status")
11110     # don't restore from ebp
11111     81 0/subop/add %esp 8/imm32
11112     # . epilogue
11113     5d/pop-to-ebp
11114     c3/return
11115 
11116 test-index-with-addr-base-on-stack:
11117     # . prologue
11118     55/push-ebp
11119     89/<- %ebp 4/r32/esp
11120     # setup
11121     (clear-stream _test-input-stream)
11122     (clear-stream $_test-input-buffered-file->buffer)
11123     (clear-stream _test-output-stream)
11124     (clear-stream $_test-output-buffered-file->buffer)
11125     (clear-stream _test-error-stream)
11126     (clear-stream $_test-error-buffered-file->buffer)
11127     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11128     68/push 0/imm32
11129     68/push 0/imm32
11130     89/<- %edx 4/r32/esp
11131     (tailor-exit-descriptor %edx 0x10)
11132     #
11133     (write _test-input-stream "fn foo {\n")
11134     (write _test-input-stream "  var a: (addr array int)\n")
11135     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
11136     (write _test-input-stream "}\n")
11137     # convert
11138     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11139     # registers except esp clobbered at this point
11140     # restore ed
11141     89/<- %edx 4/r32/esp
11142     (flush _test-output-buffered-file)
11143     (flush _test-error-buffered-file)
11144 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11150     # check output
11151     (check-stream-equal _test-output-stream  ""  "F - test-index-with-addr-base-on-stack: output should be empty")
11152     (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")
11153     # check that stop(1) was called
11154     (check-ints-equal *(edx+4) 2 "F - test-index-with-addr-base-on-stack: exit status")
11155     # don't restore from ebp
11156     81 0/subop/add %esp 8/imm32
11157     # . epilogue
11158     5d/pop-to-ebp
11159     c3/return
11160 
11161 test-index-with-wrong-index-type:
11162     # . prologue
11163     55/push-ebp
11164     89/<- %ebp 4/r32/esp
11165     # setup
11166     (clear-stream _test-input-stream)
11167     (clear-stream $_test-input-buffered-file->buffer)
11168     (clear-stream _test-output-stream)
11169     (clear-stream $_test-output-buffered-file->buffer)
11170     (clear-stream _test-error-stream)
11171     (clear-stream $_test-error-buffered-file->buffer)
11172     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11173     68/push 0/imm32
11174     68/push 0/imm32
11175     89/<- %edx 4/r32/esp
11176     (tailor-exit-descriptor %edx 0x10)
11177     #
11178     (write _test-input-stream "fn foo {\n")
11179     (write _test-input-stream "  var a/eax: (addr array int) <- copy 0\n")
11180     (write _test-input-stream "  var b: boolean\n")
11181     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
11182     (write _test-input-stream "}\n")
11183     # convert
11184     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11185     # registers except esp clobbered at this point
11186     # restore ed
11187     89/<- %edx 4/r32/esp
11188     (flush _test-output-buffered-file)
11189     (flush _test-error-buffered-file)
11190 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11196     # check output
11197     (check-stream-equal _test-output-stream  ""  "F - test-index-with-wrong-index-type: output should be empty")
11198     (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")
11199     # check that stop(1) was called
11200     (check-ints-equal *(edx+4) 2 "F - test-index-with-wrong-index-type: exit status")
11201     # don't restore from ebp
11202     81 0/subop/add %esp 8/imm32
11203     # . epilogue
11204     5d/pop-to-ebp
11205     c3/return
11206 
11207 test-index-with-offset-atom-index-type:
11208     # . prologue
11209     55/push-ebp
11210     89/<- %ebp 4/r32/esp
11211     # setup
11212     (clear-stream _test-input-stream)
11213     (clear-stream $_test-input-buffered-file->buffer)
11214     (clear-stream _test-output-stream)
11215     (clear-stream $_test-output-buffered-file->buffer)
11216     (clear-stream _test-error-stream)
11217     (clear-stream $_test-error-buffered-file->buffer)
11218     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11219     68/push 0/imm32
11220     68/push 0/imm32
11221     89/<- %edx 4/r32/esp
11222     (tailor-exit-descriptor %edx 0x10)
11223     #
11224     (write _test-input-stream "fn foo {\n")
11225     (write _test-input-stream "  var a/eax: (addr array int) <- copy 0\n")
11226     (write _test-input-stream "  var b: offset\n")
11227     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
11228     (write _test-input-stream "}\n")
11229     # convert
11230     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11231     # registers except esp clobbered at this point
11232     # restore ed
11233     89/<- %edx 4/r32/esp
11234     (flush _test-output-buffered-file)
11235     (flush _test-error-buffered-file)
11236 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11242     # check output
11243     (check-stream-equal _test-output-stream  ""  "F - test-index-with-offset-atom-index-type: output should be empty")
11244     (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")
11245     # check that stop(1) was called
11246     (check-ints-equal *(edx+4) 2 "F - test-index-with-offset-atom-index-type: exit status")
11247     # don't restore from ebp
11248     81 0/subop/add %esp 8/imm32
11249     # . epilogue
11250     5d/pop-to-ebp
11251     c3/return
11252 
11253 test-index-with-offset-on-stack:
11254     # . prologue
11255     55/push-ebp
11256     89/<- %ebp 4/r32/esp
11257     # setup
11258     (clear-stream _test-input-stream)
11259     (clear-stream $_test-input-buffered-file->buffer)
11260     (clear-stream _test-output-stream)
11261     (clear-stream $_test-output-buffered-file->buffer)
11262     (clear-stream _test-error-stream)
11263     (clear-stream $_test-error-buffered-file->buffer)
11264     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11265     68/push 0/imm32
11266     68/push 0/imm32
11267     89/<- %edx 4/r32/esp
11268     (tailor-exit-descriptor %edx 0x10)
11269     #
11270     (write _test-input-stream "fn foo {\n")
11271     (write _test-input-stream "  var a/eax: (addr array int) <- copy 0\n")
11272     (write _test-input-stream "  var b: int\n")
11273     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
11274     (write _test-input-stream "}\n")
11275     # convert
11276     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11277     # registers except esp clobbered at this point
11278     # restore ed
11279     89/<- %edx 4/r32/esp
11280     (flush _test-output-buffered-file)
11281     (flush _test-error-buffered-file)
11282 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11288     # check output
11289     (check-stream-equal _test-output-stream  ""  "F - test-index-with-offset-on-stack: output should be empty")
11290     (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")
11291     # check that stop(1) was called
11292     (check-ints-equal *(edx+4) 2 "F - test-index-with-offset-on-stack: exit status")
11293     # don't restore from ebp
11294     81 0/subop/add %esp 8/imm32
11295     # . epilogue
11296     5d/pop-to-ebp
11297     c3/return
11298 
11299 test-index-needs-offset-type:
11300     # . prologue
11301     55/push-ebp
11302     89/<- %ebp 4/r32/esp
11303     # setup
11304     (clear-stream _test-input-stream)
11305     (clear-stream $_test-input-buffered-file->buffer)
11306     (clear-stream _test-output-stream)
11307     (clear-stream $_test-output-buffered-file->buffer)
11308     (clear-stream _test-error-stream)
11309     (clear-stream $_test-error-buffered-file->buffer)
11310     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11311     68/push 0/imm32
11312     68/push 0/imm32
11313     89/<- %edx 4/r32/esp
11314     (tailor-exit-descriptor %edx 0x10)
11315     #
11316     (write _test-input-stream "fn foo {\n")
11317     (write _test-input-stream "  var a/eax: (addr array t) <- copy 0\n")
11318     (write _test-input-stream "  var b/ebx: int <- copy 0\n")
11319     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
11320     (write _test-input-stream "}\n")
11321     (write _test-input-stream "type t {\n")  # size 12 is not a power of two
11322     (write _test-input-stream "  x: int\n")
11323     (write _test-input-stream "  y: int\n")
11324     (write _test-input-stream "  z: int\n")
11325     (write _test-input-stream "}\n")
11326     # convert
11327     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11328     # registers except esp clobbered at this point
11329     # restore ed
11330     89/<- %edx 4/r32/esp
11331     (flush _test-output-buffered-file)
11332     (flush _test-error-buffered-file)
11333 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11339     # check output
11340     (check-stream-equal _test-output-stream  ""  "F - test-index-needs-offset-type: output should be empty")
11341     (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")
11342     # check that stop(1) was called
11343     (check-ints-equal *(edx+4) 2 "F - test-index-needs-offset-type: exit status")
11344     # don't restore from ebp
11345     81 0/subop/add %esp 8/imm32
11346     # . epilogue
11347     5d/pop-to-ebp
11348     c3/return
11349 
11350 test-index-with-output-not-address:
11351     # . prologue
11352     55/push-ebp
11353     89/<- %ebp 4/r32/esp
11354     # setup
11355     (clear-stream _test-input-stream)
11356     (clear-stream $_test-input-buffered-file->buffer)
11357     (clear-stream _test-output-stream)
11358     (clear-stream $_test-output-buffered-file->buffer)
11359     (clear-stream _test-error-stream)
11360     (clear-stream $_test-error-buffered-file->buffer)
11361     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11362     68/push 0/imm32
11363     68/push 0/imm32
11364     89/<- %edx 4/r32/esp
11365     (tailor-exit-descriptor %edx 0x10)
11366     #
11367     (write _test-input-stream "fn foo {\n")
11368     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
11369     (write _test-input-stream "  var o/edi: int <- index a, 0\n")
11370     (write _test-input-stream "}\n")
11371     # convert
11372     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11373     # registers except esp clobbered at this point
11374     # restore ed
11375     89/<- %edx 4/r32/esp
11376     (flush _test-output-buffered-file)
11377     (flush _test-error-buffered-file)
11378 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11384     # check output
11385     (check-stream-equal _test-output-stream  ""  "F - test-index-with-output-not-address: output should be empty")
11386     (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")
11387     # check that stop(1) was called
11388     (check-ints-equal *(edx+4) 2 "F - test-index-with-output-not-address: exit status")
11389     # don't restore from ebp
11390     81 0/subop/add %esp 8/imm32
11391     # . epilogue
11392     5d/pop-to-ebp
11393     c3/return
11394 
11395 test-index-with-output-not-address-2:
11396     # . prologue
11397     55/push-ebp
11398     89/<- %ebp 4/r32/esp
11399     # setup
11400     (clear-stream _test-input-stream)
11401     (clear-stream $_test-input-buffered-file->buffer)
11402     (clear-stream _test-output-stream)
11403     (clear-stream $_test-output-buffered-file->buffer)
11404     (clear-stream _test-error-stream)
11405     (clear-stream $_test-error-buffered-file->buffer)
11406     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11407     68/push 0/imm32
11408     68/push 0/imm32
11409     89/<- %edx 4/r32/esp
11410     (tailor-exit-descriptor %edx 0x10)
11411     #
11412     (write _test-input-stream "fn foo {\n")
11413     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
11414     (write _test-input-stream "  var o/edi: (int) <- index a, 0\n")
11415     (write _test-input-stream "}\n")
11416     # convert
11417     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11418     # registers except esp clobbered at this point
11419     # restore ed
11420     89/<- %edx 4/r32/esp
11421     (flush _test-output-buffered-file)
11422     (flush _test-error-buffered-file)
11423 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11429     # check output
11430     (check-stream-equal _test-output-stream  ""  "F - test-index-with-output-not-address-2: output should be empty")
11431     (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")
11432     # check that stop(1) was called
11433     (check-ints-equal *(edx+4) 2 "F - test-index-with-output-not-address-2: exit status")
11434     # don't restore from ebp
11435     81 0/subop/add %esp 8/imm32
11436     # . epilogue
11437     5d/pop-to-ebp
11438     c3/return
11439 
11440 test-index-with-wrong-output-type:
11441     # . prologue
11442     55/push-ebp
11443     89/<- %ebp 4/r32/esp
11444     # setup
11445     (clear-stream _test-input-stream)
11446     (clear-stream $_test-input-buffered-file->buffer)
11447     (clear-stream _test-output-stream)
11448     (clear-stream $_test-output-buffered-file->buffer)
11449     (clear-stream _test-error-stream)
11450     (clear-stream $_test-error-buffered-file->buffer)
11451     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11452     68/push 0/imm32
11453     68/push 0/imm32
11454     89/<- %edx 4/r32/esp
11455     (tailor-exit-descriptor %edx 0x10)
11456     #
11457     (write _test-input-stream "fn foo {\n")
11458     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
11459     (write _test-input-stream "  var o/edi: (addr int) <- index a, 0\n")
11460     (write _test-input-stream "}\n")
11461     # convert
11462     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11463     # registers except esp clobbered at this point
11464     # restore ed
11465     89/<- %edx 4/r32/esp
11466     (flush _test-output-buffered-file)
11467     (flush _test-error-buffered-file)
11468 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11474     # check output
11475     (check-stream-equal _test-output-stream  ""  "F - test-index-with-wrong-output-type: output should be empty")
11476     (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")
11477     # check that stop(1) was called
11478     (check-ints-equal *(edx+4) 2 "F - test-index-with-wrong-output-type: exit status")
11479     # don't restore from ebp
11480     81 0/subop/add %esp 8/imm32
11481     # . epilogue
11482     5d/pop-to-ebp
11483     c3/return
11484 
11485 test-index-with-wrong-output-compound-type:
11486     # . prologue
11487     55/push-ebp
11488     89/<- %ebp 4/r32/esp
11489     # setup
11490     (clear-stream _test-input-stream)
11491     (clear-stream $_test-input-buffered-file->buffer)
11492     (clear-stream _test-output-stream)
11493     (clear-stream $_test-output-buffered-file->buffer)
11494     (clear-stream _test-error-stream)
11495     (clear-stream $_test-error-buffered-file->buffer)
11496     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11497     68/push 0/imm32
11498     68/push 0/imm32
11499     89/<- %edx 4/r32/esp
11500     (tailor-exit-descriptor %edx 0x10)
11501     #
11502     (write _test-input-stream "fn foo {\n")
11503     (write _test-input-stream "  var a/ebx: (addr array handle boolean) <- copy 0\n")
11504     (write _test-input-stream "  var o/edi: (addr handle int) <- index a, 0\n")
11505     (write _test-input-stream "}\n")
11506     # convert
11507     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11508     # registers except esp clobbered at this point
11509     # restore ed
11510     89/<- %edx 4/r32/esp
11511     (flush _test-output-buffered-file)
11512     (flush _test-error-buffered-file)
11513 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11519     # check output
11520     (check-stream-equal _test-output-stream  ""  "F - test-index-with-wrong-output-compound-type: output should be empty")
11521     (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")
11522     # check that stop(1) was called
11523     (check-ints-equal *(edx+4) 2 "F - test-index-with-wrong-output-compound-type: exit status")
11524     # don't restore from ebp
11525     81 0/subop/add %esp 8/imm32
11526     # . epilogue
11527     5d/pop-to-ebp
11528     c3/return
11529 
11530 test-index-with-no-inouts:
11531     # . prologue
11532     55/push-ebp
11533     89/<- %ebp 4/r32/esp
11534     # setup
11535     (clear-stream _test-input-stream)
11536     (clear-stream $_test-input-buffered-file->buffer)
11537     (clear-stream _test-output-stream)
11538     (clear-stream $_test-output-buffered-file->buffer)
11539     (clear-stream _test-error-stream)
11540     (clear-stream $_test-error-buffered-file->buffer)
11541     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11542     68/push 0/imm32
11543     68/push 0/imm32
11544     89/<- %edx 4/r32/esp
11545     (tailor-exit-descriptor %edx 0x10)
11546     #
11547     (write _test-input-stream "fn foo {\n")
11548     (write _test-input-stream "  var c/ecx: (addr int) <- index\n")
11549     (write _test-input-stream "}\n")
11550     # convert
11551     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11552     # registers except esp clobbered at this point
11553     # restore ed
11554     89/<- %edx 4/r32/esp
11555     (flush _test-output-buffered-file)
11556     (flush _test-error-buffered-file)
11557 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11563     # check output
11564     (check-stream-equal _test-output-stream  ""  "F - test-index-with-no-inouts: output should be empty")
11565     (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")
11566     # check that stop(1) was called
11567     (check-ints-equal *(edx+4) 2 "F - test-index-with-no-inouts: exit status")
11568     # don't restore from ebp
11569     81 0/subop/add %esp 8/imm32
11570     # . epilogue
11571     5d/pop-to-ebp
11572     c3/return
11573 
11574 test-index-with-too-few-inouts:
11575     # . prologue
11576     55/push-ebp
11577     89/<- %ebp 4/r32/esp
11578     # setup
11579     (clear-stream _test-input-stream)
11580     (clear-stream $_test-input-buffered-file->buffer)
11581     (clear-stream _test-output-stream)
11582     (clear-stream $_test-output-buffered-file->buffer)
11583     (clear-stream _test-error-stream)
11584     (clear-stream $_test-error-buffered-file->buffer)
11585     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11586     68/push 0/imm32
11587     68/push 0/imm32
11588     89/<- %edx 4/r32/esp
11589     (tailor-exit-descriptor %edx 0x10)
11590     #
11591     (write _test-input-stream "fn foo {\n")
11592     (write _test-input-stream "  var a: (array int 3)\n")
11593     (write _test-input-stream "  var c/ecx: (addr int) <- index a\n")
11594     (write _test-input-stream "}\n")
11595     # convert
11596     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11597     # registers except esp clobbered at this point
11598     # restore ed
11599     89/<- %edx 4/r32/esp
11600     (flush _test-output-buffered-file)
11601     (flush _test-error-buffered-file)
11602 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11608     # check output
11609     (check-stream-equal _test-output-stream  ""  "F - test-index-with-too-few-inouts: output should be empty")
11610     (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")
11611     # check that stop(1) was called
11612     (check-ints-equal *(edx+4) 2 "F - test-index-with-too-few-inouts: exit status")
11613     # don't restore from ebp
11614     81 0/subop/add %esp 8/imm32
11615     # . epilogue
11616     5d/pop-to-ebp
11617     c3/return
11618 
11619 test-index-with-too-many-inouts:
11620     # . prologue
11621     55/push-ebp
11622     89/<- %ebp 4/r32/esp
11623     # setup
11624     (clear-stream _test-input-stream)
11625     (clear-stream $_test-input-buffered-file->buffer)
11626     (clear-stream _test-output-stream)
11627     (clear-stream $_test-output-buffered-file->buffer)
11628     (clear-stream _test-error-stream)
11629     (clear-stream $_test-error-buffered-file->buffer)
11630     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11631     68/push 0/imm32
11632     68/push 0/imm32
11633     89/<- %edx 4/r32/esp
11634     (tailor-exit-descriptor %edx 0x10)
11635     #
11636     (write _test-input-stream "fn foo {\n")
11637     (write _test-input-stream "  var a: (array int 3)\n")
11638     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0, 0\n")
11639     (write _test-input-stream "}\n")
11640     # convert
11641     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11642     # registers except esp clobbered at this point
11643     # restore ed
11644     89/<- %edx 4/r32/esp
11645     (flush _test-output-buffered-file)
11646     (flush _test-error-buffered-file)
11647 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11653     # check output
11654     (check-stream-equal _test-output-stream  ""  "F - test-index-with-too-many-inouts: output should be empty")
11655     (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")
11656     # check that stop(1) was called
11657     (check-ints-equal *(edx+4) 2 "F - test-index-with-too-many-inouts: exit status")
11658     # don't restore from ebp
11659     81 0/subop/add %esp 8/imm32
11660     # . epilogue
11661     5d/pop-to-ebp
11662     c3/return
11663 
11664 test-index-with-no-output:
11665     # . prologue
11666     55/push-ebp
11667     89/<- %ebp 4/r32/esp
11668     # setup
11669     (clear-stream _test-input-stream)
11670     (clear-stream $_test-input-buffered-file->buffer)
11671     (clear-stream _test-output-stream)
11672     (clear-stream $_test-output-buffered-file->buffer)
11673     (clear-stream _test-error-stream)
11674     (clear-stream $_test-error-buffered-file->buffer)
11675     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11676     68/push 0/imm32
11677     68/push 0/imm32
11678     89/<- %edx 4/r32/esp
11679     (tailor-exit-descriptor %edx 0x10)
11680     #
11681     (write _test-input-stream "fn foo {\n")
11682     (write _test-input-stream "  var a: (array int 3)\n")
11683     (write _test-input-stream "  index a, 0\n")
11684     (write _test-input-stream "}\n")
11685     # convert
11686     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11687     # registers except esp clobbered at this point
11688     # restore ed
11689     89/<- %edx 4/r32/esp
11690     (flush _test-output-buffered-file)
11691     (flush _test-error-buffered-file)
11692 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11698     # check output
11699     (check-stream-equal _test-output-stream  ""  "F - test-index-with-no-output: output should be empty")
11700     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: must have an output"  "F - test-index-with-no-output: error message")
11701     # check that stop(1) was called
11702     (check-ints-equal *(edx+4) 2 "F - test-index-with-no-output: exit status")
11703     # don't restore from ebp
11704     81 0/subop/add %esp 8/imm32
11705     # . epilogue
11706     5d/pop-to-ebp
11707     c3/return
11708 
11709 test-index-with-too-many-outputs:
11710     # . prologue
11711     55/push-ebp
11712     89/<- %ebp 4/r32/esp
11713     # setup
11714     (clear-stream _test-input-stream)
11715     (clear-stream $_test-input-buffered-file->buffer)
11716     (clear-stream _test-output-stream)
11717     (clear-stream $_test-output-buffered-file->buffer)
11718     (clear-stream _test-error-stream)
11719     (clear-stream $_test-error-buffered-file->buffer)
11720     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11721     68/push 0/imm32
11722     68/push 0/imm32
11723     89/<- %edx 4/r32/esp
11724     (tailor-exit-descriptor %edx 0x10)
11725     #
11726     (write _test-input-stream "fn foo {\n")
11727     (write _test-input-stream "  var a: (array int 3)\n")
11728     (write _test-input-stream "  var b/eax: (addr int) <- copy 0\n")
11729     (write _test-input-stream "  var c/ecx: (addr int) <- copy 0\n")
11730     (write _test-input-stream "  b, c <- index a, 0\n")
11731     (write _test-input-stream "}\n")
11732     # convert
11733     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11734     # registers except esp clobbered at this point
11735     # restore ed
11736     89/<- %edx 4/r32/esp
11737     (flush _test-output-buffered-file)
11738     (flush _test-error-buffered-file)
11739 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11745     # check output
11746     (check-stream-equal _test-output-stream  ""  "F - test-index-with-too-many-outputs: output should be empty")
11747     (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")
11748     # check that stop(1) was called
11749     (check-ints-equal *(edx+4) 2 "F - test-index-with-too-many-outputs: exit status")
11750     # don't restore from ebp
11751     81 0/subop/add %esp 8/imm32
11752     # . epilogue
11753     5d/pop-to-ebp
11754     c3/return
11755 
11756 test-compute-offset-with-non-array-atom-base-type:
11757     # . prologue
11758     55/push-ebp
11759     89/<- %ebp 4/r32/esp
11760     # setup
11761     (clear-stream _test-input-stream)
11762     (clear-stream $_test-input-buffered-file->buffer)
11763     (clear-stream _test-output-stream)
11764     (clear-stream $_test-output-buffered-file->buffer)
11765     (clear-stream _test-error-stream)
11766     (clear-stream $_test-error-buffered-file->buffer)
11767     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11768     68/push 0/imm32
11769     68/push 0/imm32
11770     89/<- %edx 4/r32/esp
11771     (tailor-exit-descriptor %edx 0x10)
11772     #
11773     (write _test-input-stream "fn foo {\n")
11774     (write _test-input-stream "  var a: int\n")
11775     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0\n")
11776     (write _test-input-stream "}\n")
11777     # convert
11778     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11779     # registers except esp clobbered at this point
11780     # restore ed
11781     89/<- %edx 4/r32/esp
11782     (flush _test-output-buffered-file)
11783     (flush _test-error-buffered-file)
11784 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11790     # check output
11791     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-non-array-atom-base-type: output should be empty")
11792     (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")
11793     # check that stop(1) was called
11794     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-non-array-atom-base-type: exit status")
11795     # don't restore from ebp
11796     81 0/subop/add %esp 8/imm32
11797     # . epilogue
11798     5d/pop-to-ebp
11799     c3/return
11800 
11801 test-compute-offset-with-non-array-compound-base-type:
11802     # . prologue
11803     55/push-ebp
11804     89/<- %ebp 4/r32/esp
11805     # setup
11806     (clear-stream _test-input-stream)
11807     (clear-stream $_test-input-buffered-file->buffer)
11808     (clear-stream _test-output-stream)
11809     (clear-stream $_test-output-buffered-file->buffer)
11810     (clear-stream _test-error-stream)
11811     (clear-stream $_test-error-buffered-file->buffer)
11812     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11813     68/push 0/imm32
11814     68/push 0/imm32
11815     89/<- %edx 4/r32/esp
11816     (tailor-exit-descriptor %edx 0x10)
11817     #
11818     (write _test-input-stream "fn foo {\n")
11819     (write _test-input-stream "  var a: (handle int)\n")
11820     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0\n")
11821     (write _test-input-stream "}\n")
11822     # convert
11823     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11824     # registers except esp clobbered at this point
11825     # restore ed
11826     89/<- %edx 4/r32/esp
11827     (flush _test-output-buffered-file)
11828     (flush _test-error-buffered-file)
11829 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11835     # check output
11836     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-non-array-compound-base-type: output should be empty")
11837     (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")
11838     # check that stop(1) was called
11839     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-non-array-compound-base-type: exit status")
11840     # don't restore from ebp
11841     81 0/subop/add %esp 8/imm32
11842     # . epilogue
11843     5d/pop-to-ebp
11844     c3/return
11845 
11846 test-compute-offset-with-non-array-compound-base-type-2:
11847     # . prologue
11848     55/push-ebp
11849     89/<- %ebp 4/r32/esp
11850     # setup
11851     (clear-stream _test-input-stream)
11852     (clear-stream $_test-input-buffered-file->buffer)
11853     (clear-stream _test-output-stream)
11854     (clear-stream $_test-output-buffered-file->buffer)
11855     (clear-stream _test-error-stream)
11856     (clear-stream $_test-error-buffered-file->buffer)
11857     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11858     68/push 0/imm32
11859     68/push 0/imm32
11860     89/<- %edx 4/r32/esp
11861     (tailor-exit-descriptor %edx 0x10)
11862     #
11863     (write _test-input-stream "fn foo {\n")
11864     (write _test-input-stream "  var a: (addr int)\n")
11865     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0\n")
11866     (write _test-input-stream "}\n")
11867     # convert
11868     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11869     # registers except esp clobbered at this point
11870     # restore ed
11871     89/<- %edx 4/r32/esp
11872     (flush _test-output-buffered-file)
11873     (flush _test-error-buffered-file)
11874 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11880     # check output
11881     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-non-array-compound-base-type-2: output should be empty")
11882     (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")
11883     # check that stop(1) was called
11884     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-non-array-compound-base-type-2: exit status")
11885     # don't restore from ebp
11886     81 0/subop/add %esp 8/imm32
11887     # . epilogue
11888     5d/pop-to-ebp
11889     c3/return
11890 
11891 test-compute-offset-with-array-atom-base-type:
11892     # . prologue
11893     55/push-ebp
11894     89/<- %ebp 4/r32/esp
11895     # setup
11896     (clear-stream _test-input-stream)
11897     (clear-stream $_test-input-buffered-file->buffer)
11898     (clear-stream _test-output-stream)
11899     (clear-stream $_test-output-buffered-file->buffer)
11900     (clear-stream _test-error-stream)
11901     (clear-stream $_test-error-buffered-file->buffer)
11902     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11903     68/push 0/imm32
11904     68/push 0/imm32
11905     89/<- %edx 4/r32/esp
11906     (tailor-exit-descriptor %edx 0x10)
11907     #
11908     (write _test-input-stream "fn foo {\n")
11909     (write _test-input-stream "  var a: array\n")
11910     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0\n")
11911     (write _test-input-stream "}\n")
11912     # convert
11913     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11914     # registers except esp clobbered at this point
11915     # restore ed
11916     89/<- %edx 4/r32/esp
11917     (flush _test-output-buffered-file)
11918     (flush _test-error-buffered-file)
11919 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11925     # check output
11926     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-array-atom-base-type: output should be empty")
11927     (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")
11928     # check that stop(1) was called
11929     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-array-atom-base-type: exit status")
11930     # don't restore from ebp
11931     81 0/subop/add %esp 8/imm32
11932     # . epilogue
11933     5d/pop-to-ebp
11934     c3/return
11935 
11936 test-compute-offset-with-wrong-index-type:
11937     # . prologue
11938     55/push-ebp
11939     89/<- %ebp 4/r32/esp
11940     # setup
11941     (clear-stream _test-input-stream)
11942     (clear-stream $_test-input-buffered-file->buffer)
11943     (clear-stream _test-output-stream)
11944     (clear-stream $_test-output-buffered-file->buffer)
11945     (clear-stream _test-error-stream)
11946     (clear-stream $_test-error-buffered-file->buffer)
11947     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11948     68/push 0/imm32
11949     68/push 0/imm32
11950     89/<- %edx 4/r32/esp
11951     (tailor-exit-descriptor %edx 0x10)
11952     #
11953     (write _test-input-stream "fn foo {\n")
11954     (write _test-input-stream "  var a/eax: (addr array int) <- copy 0\n")
11955     (write _test-input-stream "  var b: boolean\n")
11956     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, b\n")
11957     (write _test-input-stream "}\n")
11958     # convert
11959     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11960     # registers except esp clobbered at this point
11961     # restore ed
11962     89/<- %edx 4/r32/esp
11963     (flush _test-output-buffered-file)
11964     (flush _test-error-buffered-file)
11965 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11971     # check output
11972     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-wrong-index-type: output should be empty")
11973     (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")
11974     # check that stop(1) was called
11975     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-wrong-index-type: exit status")
11976     # don't restore from ebp
11977     81 0/subop/add %esp 8/imm32
11978     # . epilogue
11979     5d/pop-to-ebp
11980     c3/return
11981 
11982 test-compute-offset-with-output-not-offset:
11983     # . prologue
11984     55/push-ebp
11985     89/<- %ebp 4/r32/esp
11986     # setup
11987     (clear-stream _test-input-stream)
11988     (clear-stream $_test-input-buffered-file->buffer)
11989     (clear-stream _test-output-stream)
11990     (clear-stream $_test-output-buffered-file->buffer)
11991     (clear-stream _test-error-stream)
11992     (clear-stream $_test-error-buffered-file->buffer)
11993     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11994     68/push 0/imm32
11995     68/push 0/imm32
11996     89/<- %edx 4/r32/esp
11997     (tailor-exit-descriptor %edx 0x10)
11998     #
11999     (write _test-input-stream "fn foo {\n")
12000     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
12001     (write _test-input-stream "  var o/edi: int <- compute-offset a, 0\n")
12002     (write _test-input-stream "}\n")
12003     # convert
12004     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12005     # registers except esp clobbered at this point
12006     # restore ed
12007     89/<- %edx 4/r32/esp
12008     (flush _test-output-buffered-file)
12009     (flush _test-error-buffered-file)
12010 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12016     # check output
12017     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-output-not-offset: output should be empty")
12018     (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")
12019     # check that stop(1) was called
12020     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-output-not-offset: exit status")
12021     # don't restore from ebp
12022     81 0/subop/add %esp 8/imm32
12023     # . epilogue
12024     5d/pop-to-ebp
12025     c3/return
12026 
12027 test-compute-offset-with-output-not-address-2:
12028     # . prologue
12029     55/push-ebp
12030     89/<- %ebp 4/r32/esp
12031     # setup
12032     (clear-stream _test-input-stream)
12033     (clear-stream $_test-input-buffered-file->buffer)
12034     (clear-stream _test-output-stream)
12035     (clear-stream $_test-output-buffered-file->buffer)
12036     (clear-stream _test-error-stream)
12037     (clear-stream $_test-error-buffered-file->buffer)
12038     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12039     68/push 0/imm32
12040     68/push 0/imm32
12041     89/<- %edx 4/r32/esp
12042     (tailor-exit-descriptor %edx 0x10)
12043     #
12044     (write _test-input-stream "fn foo {\n")
12045     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
12046     (write _test-input-stream "  var o/edi: (int) <- compute-offset a, 0\n")
12047     (write _test-input-stream "}\n")
12048     # convert
12049     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12050     # registers except esp clobbered at this point
12051     # restore ed
12052     89/<- %edx 4/r32/esp
12053     (flush _test-output-buffered-file)
12054     (flush _test-error-buffered-file)
12055 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12061     # check output
12062     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-output-not-address-2: output should be empty")
12063     (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")
12064     # check that stop(1) was called
12065     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-output-not-address-2: exit status")
12066     # don't restore from ebp
12067     81 0/subop/add %esp 8/imm32
12068     # . epilogue
12069     5d/pop-to-ebp
12070     c3/return
12071 
12072 test-compute-offset-with-wrong-output-type:
12073     # . prologue
12074     55/push-ebp
12075     89/<- %ebp 4/r32/esp
12076     # setup
12077     (clear-stream _test-input-stream)
12078     (clear-stream $_test-input-buffered-file->buffer)
12079     (clear-stream _test-output-stream)
12080     (clear-stream $_test-output-buffered-file->buffer)
12081     (clear-stream _test-error-stream)
12082     (clear-stream $_test-error-buffered-file->buffer)
12083     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12084     68/push 0/imm32
12085     68/push 0/imm32
12086     89/<- %edx 4/r32/esp
12087     (tailor-exit-descriptor %edx 0x10)
12088     #
12089     (write _test-input-stream "fn foo {\n")
12090     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
12091     (write _test-input-stream "  var o/edi: (offset int) <- compute-offset a, 0\n")
12092     (write _test-input-stream "}\n")
12093     # convert
12094     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12095     # registers except esp clobbered at this point
12096     # restore ed
12097     89/<- %edx 4/r32/esp
12098     (flush _test-output-buffered-file)
12099     (flush _test-error-buffered-file)
12100 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12106     # check output
12107     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-wrong-output-type: output should be empty")
12108     (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")
12109     # check that stop(1) was called
12110     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-wrong-output-type: exit status")
12111     # don't restore from ebp
12112     81 0/subop/add %esp 8/imm32
12113     # . epilogue
12114     5d/pop-to-ebp
12115     c3/return
12116 
12117 test-compute-offset-with-wrong-output-compound-type:
12118     # . prologue
12119     55/push-ebp
12120     89/<- %ebp 4/r32/esp
12121     # setup
12122     (clear-stream _test-input-stream)
12123     (clear-stream $_test-input-buffered-file->buffer)
12124     (clear-stream _test-output-stream)
12125     (clear-stream $_test-output-buffered-file->buffer)
12126     (clear-stream _test-error-stream)
12127     (clear-stream $_test-error-buffered-file->buffer)
12128     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12129     68/push 0/imm32
12130     68/push 0/imm32
12131     89/<- %edx 4/r32/esp
12132     (tailor-exit-descriptor %edx 0x10)
12133     #
12134     (write _test-input-stream "fn foo {\n")
12135     (write _test-input-stream "  var a/ebx: (addr array handle boolean) <- copy 0\n")
12136     (write _test-input-stream "  var o/edi: (offset handle int) <- compute-offset a, 0\n")
12137     (write _test-input-stream "}\n")
12138     # convert
12139     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12140     # registers except esp clobbered at this point
12141     # restore ed
12142     89/<- %edx 4/r32/esp
12143     (flush _test-output-buffered-file)
12144     (flush _test-error-buffered-file)
12145 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12151     # check output
12152     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-wrong-output-compound-type: output should be empty")
12153     (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")
12154     # check that stop(1) was called
12155     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-wrong-output-compound-type: exit status")
12156     # don't restore from ebp
12157     81 0/subop/add %esp 8/imm32
12158     # . epilogue
12159     5d/pop-to-ebp
12160     c3/return
12161 
12162 test-compute-offset-with-no-inouts:
12163     # . prologue
12164     55/push-ebp
12165     89/<- %ebp 4/r32/esp
12166     # setup
12167     (clear-stream _test-input-stream)
12168     (clear-stream $_test-input-buffered-file->buffer)
12169     (clear-stream _test-output-stream)
12170     (clear-stream $_test-output-buffered-file->buffer)
12171     (clear-stream _test-error-stream)
12172     (clear-stream $_test-error-buffered-file->buffer)
12173     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12174     68/push 0/imm32
12175     68/push 0/imm32
12176     89/<- %edx 4/r32/esp
12177     (tailor-exit-descriptor %edx 0x10)
12178     #
12179     (write _test-input-stream "fn foo {\n")
12180     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset\n")
12181     (write _test-input-stream "}\n")
12182     # convert
12183     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12184     # registers except esp clobbered at this point
12185     # restore ed
12186     89/<- %edx 4/r32/esp
12187     (flush _test-output-buffered-file)
12188     (flush _test-error-buffered-file)
12189 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12195     # check output
12196     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-no-inouts: output should be empty")
12197     (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")
12198     # check that stop(1) was called
12199     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-no-inouts: exit status")
12200     # don't restore from ebp
12201     81 0/subop/add %esp 8/imm32
12202     # . epilogue
12203     5d/pop-to-ebp
12204     c3/return
12205 
12206 test-compute-offset-with-too-few-inouts:
12207     # . prologue
12208     55/push-ebp
12209     89/<- %ebp 4/r32/esp
12210     # setup
12211     (clear-stream _test-input-stream)
12212     (clear-stream $_test-input-buffered-file->buffer)
12213     (clear-stream _test-output-stream)
12214     (clear-stream $_test-output-buffered-file->buffer)
12215     (clear-stream _test-error-stream)
12216     (clear-stream $_test-error-buffered-file->buffer)
12217     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12218     68/push 0/imm32
12219     68/push 0/imm32
12220     89/<- %edx 4/r32/esp
12221     (tailor-exit-descriptor %edx 0x10)
12222     #
12223     (write _test-input-stream "fn foo {\n")
12224     (write _test-input-stream "  var a: (array int 3)\n")
12225     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a\n")
12226     (write _test-input-stream "}\n")
12227     # convert
12228     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12229     # registers except esp clobbered at this point
12230     # restore ed
12231     89/<- %edx 4/r32/esp
12232     (flush _test-output-buffered-file)
12233     (flush _test-error-buffered-file)
12234 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12240     # check output
12241     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-too-few-inouts: output should be empty")
12242     (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")
12243     # check that stop(1) was called
12244     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-too-few-inouts: exit status")
12245     # don't restore from ebp
12246     81 0/subop/add %esp 8/imm32
12247     # . epilogue
12248     5d/pop-to-ebp
12249     c3/return
12250 
12251 test-compute-offset-with-too-many-inouts:
12252     # . prologue
12253     55/push-ebp
12254     89/<- %ebp 4/r32/esp
12255     # setup
12256     (clear-stream _test-input-stream)
12257     (clear-stream $_test-input-buffered-file->buffer)
12258     (clear-stream _test-output-stream)
12259     (clear-stream $_test-output-buffered-file->buffer)
12260     (clear-stream _test-error-stream)
12261     (clear-stream $_test-error-buffered-file->buffer)
12262     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12263     68/push 0/imm32
12264     68/push 0/imm32
12265     89/<- %edx 4/r32/esp
12266     (tailor-exit-descriptor %edx 0x10)
12267     #
12268     (write _test-input-stream "fn foo {\n")
12269     (write _test-input-stream "  var a: (array int 3)\n")
12270     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0, 0\n")
12271     (write _test-input-stream "}\n")
12272     # convert
12273     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12274     # registers except esp clobbered at this point
12275     # restore ed
12276     89/<- %edx 4/r32/esp
12277     (flush _test-output-buffered-file)
12278     (flush _test-error-buffered-file)
12279 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12285     # check output
12286     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-too-many-inouts: output should be empty")
12287     (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")
12288     # check that stop(1) was called
12289     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-too-many-inouts: exit status")
12290     # don't restore from ebp
12291     81 0/subop/add %esp 8/imm32
12292     # . epilogue
12293     5d/pop-to-ebp
12294     c3/return
12295 
12296 test-compute-offset-with-no-output:
12297     # . prologue
12298     55/push-ebp
12299     89/<- %ebp 4/r32/esp
12300     # setup
12301     (clear-stream _test-input-stream)
12302     (clear-stream $_test-input-buffered-file->buffer)
12303     (clear-stream _test-output-stream)
12304     (clear-stream $_test-output-buffered-file->buffer)
12305     (clear-stream _test-error-stream)
12306     (clear-stream $_test-error-buffered-file->buffer)
12307     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12308     68/push 0/imm32
12309     68/push 0/imm32
12310     89/<- %edx 4/r32/esp
12311     (tailor-exit-descriptor %edx 0x10)
12312     #
12313     (write _test-input-stream "fn foo {\n")
12314     (write _test-input-stream "  var a: (array int 3)\n")
12315     (write _test-input-stream "  compute-offset a, 0\n")
12316     (write _test-input-stream "}\n")
12317     # convert
12318     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12319     # registers except esp clobbered at this point
12320     # restore ed
12321     89/<- %edx 4/r32/esp
12322     (flush _test-output-buffered-file)
12323     (flush _test-error-buffered-file)
12324 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12330     # check output
12331     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-no-output: output should be empty")
12332     (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")
12333     # check that stop(1) was called
12334     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-no-output: exit status")
12335     # don't restore from ebp
12336     81 0/subop/add %esp 8/imm32
12337     # . epilogue
12338     5d/pop-to-ebp
12339     c3/return
12340 
12341 test-compute-offset-with-too-many-outputs:
12342     # . prologue
12343     55/push-ebp
12344     89/<- %ebp 4/r32/esp
12345     # setup
12346     (clear-stream _test-input-stream)
12347     (clear-stream $_test-input-buffered-file->buffer)
12348     (clear-stream _test-output-stream)
12349     (clear-stream $_test-output-buffered-file->buffer)
12350     (clear-stream _test-error-stream)
12351     (clear-stream $_test-error-buffered-file->buffer)
12352     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12353     68/push 0/imm32
12354     68/push 0/imm32
12355     89/<- %edx 4/r32/esp
12356     (tailor-exit-descriptor %edx 0x10)
12357     #
12358     (write _test-input-stream "fn foo {\n")
12359     (write _test-input-stream "  var a: (array int 3)\n")
12360     (write _test-input-stream "  var b/eax: (offset int) <- compute-offset a, 0\n")
12361     (write _test-input-stream "  var c/ecx: (addr int) <- copy 0\n")
12362     (write _test-input-stream "  b, c <- compute-offset a, 0\n")
12363     (write _test-input-stream "}\n")
12364     # convert
12365     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12366     # registers except esp clobbered at this point
12367     # restore ed
12368     89/<- %edx 4/r32/esp
12369     (flush _test-output-buffered-file)
12370     (flush _test-error-buffered-file)
12371 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12377     # check output
12378     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-too-many-outputs: output should be empty")
12379     (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")
12380     # check that stop(1) was called
12381     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-too-many-outputs: exit status")
12382     # don't restore from ebp
12383     81 0/subop/add %esp 8/imm32
12384     # . epilogue
12385     5d/pop-to-ebp
12386     c3/return
12387 
12388 test-convert-read-from-stream:
12389     # . prologue
12390     55/push-ebp
12391     89/<- %ebp 4/r32/esp
12392     # setup
12393     (clear-stream _test-input-stream)
12394     (clear-stream $_test-input-buffered-file->buffer)
12395     (clear-stream _test-output-stream)
12396     (clear-stream $_test-output-buffered-file->buffer)
12397     #
12398     (write _test-input-stream "fn foo {\n")
12399     (write _test-input-stream "  var s/esi: (addr stream int) <- copy 0\n")
12400     (write _test-input-stream "  var o/ecx: (addr int) <- copy 0\n")
12401     (write _test-input-stream "  read-from-stream s, o\n")
12402     (write _test-input-stream "}\n")
12403     # convert
12404     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
12405     # registers except esp clobbered at this point
12406     # restore ed
12407     89/<- %edx 4/r32/esp
12408     (flush _test-output-buffered-file)
12409     (flush _test-error-buffered-file)
12410 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
12416     # check output
12417     (check-next-stream-line-equal _test-output-stream "foo:"                            "F - test-convert-read-from-stream/0")
12418     (check-next-stream-line-equal _test-output-stream "  # . prologue"                  "F - test-convert-read-from-stream/1")
12419     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                   "F - test-convert-read-from-stream/2")
12420     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"          "F - test-convert-read-from-stream/3")
12421     (check-next-stream-line-equal _test-output-stream "  {"                             "F - test-convert-read-from-stream/4")
12422     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"           "F - test-convert-read-from-stream/5")
12423     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %esi"        "F - test-convert-read-from-stream/6")
12424     (check-next-stream-line-equal _test-output-stream "    be/copy-to-esi 0/imm32"      "F - test-convert-read-from-stream/7")
12425     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"        "F - test-convert-read-from-stream/8")
12426     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"      "F - test-convert-read-from-stream/9")
12427     (check-next-stream-line-equal _test-output-stream "    (read-from-stream %esi %ecx 0x00000004)"  "F - test-convert-read-from-stream/10")
12428     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-read-from-stream/11")
12429     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %esi"         "F - test-convert-read-from-stream/12")
12430     (check-next-stream-line-equal _test-output-stream "  }"                             "F - test-convert-read-from-stream/13")
12431     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"          "F - test-convert-read-from-stream/14")
12432     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                  "F - test-convert-read-from-stream/15")
12433     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"          "F - test-convert-read-from-stream/16")
12434     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                 "F - test-convert-read-from-stream/17")
12435     (check-next-stream-line-equal _test-output-stream "  c3/return"                     "F - test-convert-read-from-stream/18")
12436     # . epilogue
12437     89/<- %esp 5/r32/ebp
12438     5d/pop-to-ebp
12439     c3/return
12440 
12441 test-convert-read-from-stream-with-correct-payload-size:
12442     # . prologue
12443     55/push-ebp
12444     89/<- %ebp 4/r32/esp
12445     # setup
12446     (clear-stream _test-input-stream)
12447     (clear-stream $_test-input-buffered-file->buffer)
12448     (clear-stream _test-output-stream)
12449     (clear-stream $_test-output-buffered-file->buffer)
12450     #
12451     (write _test-input-stream "fn foo {\n")
12452     (write _test-input-stream "  var s/esi: (addr stream handle int) <- copy 0\n")
12453     (write _test-input-stream "  var o/ecx: (addr handle int) <- copy 0\n")
12454     (write _test-input-stream "  read-from-stream s, o\n")
12455     (write _test-input-stream "}\n")
12456     # convert
12457     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
12458     # registers except esp clobbered at this point
12459     # restore ed
12460     89/<- %edx 4/r32/esp
12461     (flush _test-output-buffered-file)
12462     (flush _test-error-buffered-file)
12463 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
12469     # check output
12470     (check-next-stream-line-equal _test-output-stream "foo:"                            "F - test-convert-read-from-stream-with-correct-payload-size/0")
12471     (check-next-stream-line-equal _test-output-stream "  # . prologue"                  "F - test-convert-read-from-stream-with-correct-payload-size/1")
12472     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                   "F - test-convert-read-from-stream-with-correct-payload-size/2")
12473     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"          "F - test-convert-read-from-stream-with-correct-payload-size/3")
12474     (check-next-stream-line-equal _test-output-stream "  {"                             "F - test-convert-read-from-stream-with-correct-payload-size/4")
12475     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"           "F - test-convert-read-from-stream-with-correct-payload-size/5")
12476     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %esi"        "F - test-convert-read-from-stream-with-correct-payload-size/6")
12477     (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")
12478     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"        "F - test-convert-read-from-stream-with-correct-payload-size/8")
12479     (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")
12480     (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")
12481     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-read-from-stream-with-correct-payload-size/11")
12482     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %esi"         "F - test-convert-read-from-stream-with-correct-payload-size/12")
12483     (check-next-stream-line-equal _test-output-stream "  }"                             "F - test-convert-read-from-stream-with-correct-payload-size/13")
12484     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"          "F - test-convert-read-from-stream-with-correct-payload-size/14")
12485     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                  "F - test-convert-read-from-stream-with-correct-payload-size/15")
12486     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"          "F - test-convert-read-from-stream-with-correct-payload-size/16")
12487     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                 "F - test-convert-read-from-stream-with-correct-payload-size/17")
12488     (check-next-stream-line-equal _test-output-stream "  c3/return"                     "F - test-convert-read-from-stream-with-correct-payload-size/18")
12489     # . epilogue
12490     89/<- %esp 5/r32/ebp
12491     5d/pop-to-ebp
12492     c3/return
12493 
12494 test-read-from-stream-with-non-stream-atom-base-type:
12495     # . prologue
12496     55/push-ebp
12497     89/<- %ebp 4/r32/esp
12498     # setup
12499     (clear-stream _test-input-stream)
12500     (clear-stream $_test-input-buffered-file->buffer)
12501     (clear-stream _test-output-stream)
12502     (clear-stream $_test-output-buffered-file->buffer)
12503     (clear-stream _test-error-stream)
12504     (clear-stream $_test-error-buffered-file->buffer)
12505     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12506     68/push 0/imm32
12507     68/push 0/imm32
12508     89/<- %edx 4/r32/esp
12509     (tailor-exit-descriptor %edx 0x10)
12510     #
12511     (write _test-input-stream "fn foo {\n")
12512     (write _test-input-stream "  var a: int\n")
12513     (write _test-input-stream "  read-from-stream a, 0\n")
12514     (write _test-input-stream "}\n")
12515     # convert
12516     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12517     # registers except esp clobbered at this point
12518     # restore ed
12519     89/<- %edx 4/r32/esp
12520     (flush _test-output-buffered-file)
12521     (flush _test-error-buffered-file)
12522 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12528     # check output
12529     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-non-stream-atom-base-type: output should be empty")
12530     (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")
12531     # check that stop(1) was called
12532     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-non-stream-atom-base-type: exit status")
12533     # don't restore from ebp
12534     81 0/subop/add %esp 8/imm32
12535     # . epilogue
12536     5d/pop-to-ebp
12537     c3/return
12538 
12539 test-read-from-stream-with-non-stream-compound-base-type:
12540     # . prologue
12541     55/push-ebp
12542     89/<- %ebp 4/r32/esp
12543     # setup
12544     (clear-stream _test-input-stream)
12545     (clear-stream $_test-input-buffered-file->buffer)
12546     (clear-stream _test-output-stream)
12547     (clear-stream $_test-output-buffered-file->buffer)
12548     (clear-stream _test-error-stream)
12549     (clear-stream $_test-error-buffered-file->buffer)
12550     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12551     68/push 0/imm32
12552     68/push 0/imm32
12553     89/<- %edx 4/r32/esp
12554     (tailor-exit-descriptor %edx 0x10)
12555     #
12556     (write _test-input-stream "fn foo {\n")
12557     (write _test-input-stream "  var a: (handle int)\n")
12558     (write _test-input-stream "  read-from-stream a, 0\n")
12559     (write _test-input-stream "}\n")
12560     # convert
12561     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12562     # registers except esp clobbered at this point
12563     # restore ed
12564     89/<- %edx 4/r32/esp
12565     (flush _test-output-buffered-file)
12566     (flush _test-error-buffered-file)
12567 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12573     # check output
12574     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-non-stream-compound-base-type: output should be empty")
12575     (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")
12576     # check that stop(1) was called
12577     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-non-stream-compound-base-type: exit status")
12578     # don't restore from ebp
12579     81 0/subop/add %esp 8/imm32
12580     # . epilogue
12581     5d/pop-to-ebp
12582     c3/return
12583 
12584 test-read-from-stream-with-non-stream-compound-base-type-2:
12585     # . prologue
12586     55/push-ebp
12587     89/<- %ebp 4/r32/esp
12588     # setup
12589     (clear-stream _test-input-stream)
12590     (clear-stream $_test-input-buffered-file->buffer)
12591     (clear-stream _test-output-stream)
12592     (clear-stream $_test-output-buffered-file->buffer)
12593     (clear-stream _test-error-stream)
12594     (clear-stream $_test-error-buffered-file->buffer)
12595     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12596     68/push 0/imm32
12597     68/push 0/imm32
12598     89/<- %edx 4/r32/esp
12599     (tailor-exit-descriptor %edx 0x10)
12600     #
12601     (write _test-input-stream "fn foo {\n")
12602     (write _test-input-stream "  var a: (addr int)\n")
12603     (write _test-input-stream "  read-from-stream a, 0\n")
12604     (write _test-input-stream "}\n")
12605     # convert
12606     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12607     # registers except esp clobbered at this point
12608     # restore ed
12609     89/<- %edx 4/r32/esp
12610     (flush _test-output-buffered-file)
12611     (flush _test-error-buffered-file)
12612 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12618     # check output
12619     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-non-stream-compound-base-type-2: output should be empty")
12620     (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")
12621     # check that stop(1) was called
12622     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-non-stream-compound-base-type-2: exit status")
12623     # don't restore from ebp
12624     81 0/subop/add %esp 8/imm32
12625     # . epilogue
12626     5d/pop-to-ebp
12627     c3/return
12628 
12629 test-read-from-stream-with-stream-atom-base-type:
12630     # . prologue
12631     55/push-ebp
12632     89/<- %ebp 4/r32/esp
12633     # setup
12634     (clear-stream _test-input-stream)
12635     (clear-stream $_test-input-buffered-file->buffer)
12636     (clear-stream _test-output-stream)
12637     (clear-stream $_test-output-buffered-file->buffer)
12638     (clear-stream _test-error-stream)
12639     (clear-stream $_test-error-buffered-file->buffer)
12640     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12641     68/push 0/imm32
12642     68/push 0/imm32
12643     89/<- %edx 4/r32/esp
12644     (tailor-exit-descriptor %edx 0x10)
12645     #
12646     (write _test-input-stream "fn foo {\n")
12647     (write _test-input-stream "  var a: stream\n")
12648     (write _test-input-stream "  read-from-stream a, 0\n")
12649     (write _test-input-stream "}\n")
12650     # convert
12651     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12652     # registers except esp clobbered at this point
12653     # restore ed
12654     89/<- %edx 4/r32/esp
12655     (flush _test-output-buffered-file)
12656     (flush _test-error-buffered-file)
12657 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12663     # check output
12664     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-stream-atom-base-type: output should be empty")
12665     (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")
12666     # check that stop(1) was called
12667     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-stream-atom-base-type: exit status")
12668     # don't restore from ebp
12669     81 0/subop/add %esp 8/imm32
12670     # . epilogue
12671     5d/pop-to-ebp
12672     c3/return
12673 
12674 test-read-from-stream-with-wrong-index-type:
12675     # . prologue
12676     55/push-ebp
12677     89/<- %ebp 4/r32/esp
12678     # setup
12679     (clear-stream _test-input-stream)
12680     (clear-stream $_test-input-buffered-file->buffer)
12681     (clear-stream _test-output-stream)
12682     (clear-stream $_test-output-buffered-file->buffer)
12683     (clear-stream _test-error-stream)
12684     (clear-stream $_test-error-buffered-file->buffer)
12685     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12686     68/push 0/imm32
12687     68/push 0/imm32
12688     89/<- %edx 4/r32/esp
12689     (tailor-exit-descriptor %edx 0x10)
12690     #
12691     (write _test-input-stream "fn foo {\n")
12692     (write _test-input-stream "  var a/eax: (addr stream int) <- copy 0\n")
12693     (write _test-input-stream "  var b: boolean\n")
12694     (write _test-input-stream "  read-from-stream a, b\n")
12695     (write _test-input-stream "}\n")
12696     # convert
12697     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12698     # registers except esp clobbered at this point
12699     # restore ed
12700     89/<- %edx 4/r32/esp
12701     (flush _test-output-buffered-file)
12702     (flush _test-error-buffered-file)
12703 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12709     # check output
12710     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-wrong-index-type: output should be empty")
12711     (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")
12712     # check that stop(1) was called
12713     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-wrong-index-type: exit status")
12714     # don't restore from ebp
12715     81 0/subop/add %esp 8/imm32
12716     # . epilogue
12717     5d/pop-to-ebp
12718     c3/return
12719 
12720 test-read-from-stream-with-no-inouts:
12721     # . prologue
12722     55/push-ebp
12723     89/<- %ebp 4/r32/esp
12724     # setup
12725     (clear-stream _test-input-stream)
12726     (clear-stream $_test-input-buffered-file->buffer)
12727     (clear-stream _test-output-stream)
12728     (clear-stream $_test-output-buffered-file->buffer)
12729     (clear-stream _test-error-stream)
12730     (clear-stream $_test-error-buffered-file->buffer)
12731     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12732     68/push 0/imm32
12733     68/push 0/imm32
12734     89/<- %edx 4/r32/esp
12735     (tailor-exit-descriptor %edx 0x10)
12736     #
12737     (write _test-input-stream "fn foo {\n")
12738     (write _test-input-stream "  read-from-stream\n")
12739     (write _test-input-stream "}\n")
12740     # convert
12741     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12742     # registers except esp clobbered at this point
12743     # restore ed
12744     89/<- %edx 4/r32/esp
12745     (flush _test-output-buffered-file)
12746     (flush _test-error-buffered-file)
12747 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12753     # check output
12754     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-no-inouts: output should be empty")
12755     (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")
12756     # check that stop(1) was called
12757     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-no-inouts: exit status")
12758     # don't restore from ebp
12759     81 0/subop/add %esp 8/imm32
12760     # . epilogue
12761     5d/pop-to-ebp
12762     c3/return
12763 
12764 test-read-from-stream-with-too-few-inouts:
12765     # . prologue
12766     55/push-ebp
12767     89/<- %ebp 4/r32/esp
12768     # setup
12769     (clear-stream _test-input-stream)
12770     (clear-stream $_test-input-buffered-file->buffer)
12771     (clear-stream _test-output-stream)
12772     (clear-stream $_test-output-buffered-file->buffer)
12773     (clear-stream _test-error-stream)
12774     (clear-stream $_test-error-buffered-file->buffer)
12775     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12776     68/push 0/imm32
12777     68/push 0/imm32
12778     89/<- %edx 4/r32/esp
12779     (tailor-exit-descriptor %edx 0x10)
12780     #
12781     (write _test-input-stream "fn foo {\n")
12782     (write _test-input-stream "  var a: (addr stream int)\n")
12783     (write _test-input-stream "  read-from-stream a\n")
12784     (write _test-input-stream "}\n")
12785     # convert
12786     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12787     # registers except esp clobbered at this point
12788     # restore ed
12789     89/<- %edx 4/r32/esp
12790     (flush _test-output-buffered-file)
12791     (flush _test-error-buffered-file)
12792 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12798     # check output
12799     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-too-few-inouts: output should be empty")
12800     (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")
12801     # check that stop(1) was called
12802     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-too-few-inouts: exit status")
12803     # don't restore from ebp
12804     81 0/subop/add %esp 8/imm32
12805     # . epilogue
12806     5d/pop-to-ebp
12807     c3/return
12808 
12809 test-read-from-stream-with-too-many-inouts:
12810     # . prologue
12811     55/push-ebp
12812     89/<- %ebp 4/r32/esp
12813     # setup
12814     (clear-stream _test-input-stream)
12815     (clear-stream $_test-input-buffered-file->buffer)
12816     (clear-stream _test-output-stream)
12817     (clear-stream $_test-output-buffered-file->buffer)
12818     (clear-stream _test-error-stream)
12819     (clear-stream $_test-error-buffered-file->buffer)
12820     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12821     68/push 0/imm32
12822     68/push 0/imm32
12823     89/<- %edx 4/r32/esp
12824     (tailor-exit-descriptor %edx 0x10)
12825     #
12826     (write _test-input-stream "fn foo {\n")
12827     (write _test-input-stream "  var a: (addr stream int)\n")
12828     (write _test-input-stream "  var b: (addr int)\n")
12829     (write _test-input-stream "  read-from-stream a, b, 0\n")
12830     (write _test-input-stream "}\n")
12831     # convert
12832     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12833     # registers except esp clobbered at this point
12834     # restore ed
12835     89/<- %edx 4/r32/esp
12836     (flush _test-output-buffered-file)
12837     (flush _test-error-buffered-file)
12838 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12844     # check output
12845     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-too-many-inouts: output should be empty")
12846     (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")
12847     # check that stop(1) was called
12848     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-too-many-inouts: exit status")
12849     # don't restore from ebp
12850     81 0/subop/add %esp 8/imm32
12851     # . epilogue
12852     5d/pop-to-ebp
12853     c3/return
12854 
12855 test-read-from-stream-with-output:
12856     # . prologue
12857     55/push-ebp
12858     89/<- %ebp 4/r32/esp
12859     # setup
12860     (clear-stream _test-input-stream)
12861     (clear-stream $_test-input-buffered-file->buffer)
12862     (clear-stream _test-output-stream)
12863     (clear-stream $_test-output-buffered-file->buffer)
12864     (clear-stream _test-error-stream)
12865     (clear-stream $_test-error-buffered-file->buffer)
12866     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12867     68/push 0/imm32
12868     68/push 0/imm32
12869     89/<- %edx 4/r32/esp
12870     (tailor-exit-descriptor %edx 0x10)
12871     #
12872     (write _test-input-stream "fn foo {\n")
12873     (write _test-input-stream "  var a: (addr stream int)\n")
12874     (write _test-input-stream "  var b/eax: (addr int) <- copy 0\n")
12875     (write _test-input-stream "  b <- read-from-stream a, b\n")
12876     (write _test-input-stream "}\n")
12877     # convert
12878     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12879     # registers except esp clobbered at this point
12880     # restore ed
12881     89/<- %edx 4/r32/esp
12882     (flush _test-output-buffered-file)
12883     (flush _test-error-buffered-file)
12884 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12890     # check output
12891     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-output: output should be empty")
12892     (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")
12893     # check that stop(1) was called
12894     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-output: exit status")
12895     # don't restore from ebp
12896     81 0/subop/add %esp 8/imm32
12897     # . epilogue
12898     5d/pop-to-ebp
12899     c3/return
12900 
12901 test-convert-write-to-stream:
12902     # . prologue
12903     55/push-ebp
12904     89/<- %ebp 4/r32/esp
12905     # setup
12906     (clear-stream _test-input-stream)
12907     (clear-stream $_test-input-buffered-file->buffer)
12908     (clear-stream _test-output-stream)
12909     (clear-stream $_test-output-buffered-file->buffer)
12910     #
12911     (write _test-input-stream "fn foo {\n")
12912     (write _test-input-stream "  var s/esi: (addr stream int) <- copy 0\n")
12913     (write _test-input-stream "  var o/ecx: (addr int) <- copy 0\n")
12914     (write _test-input-stream "  write-to-stream s, o\n")
12915     (write _test-input-stream "}\n")
12916     # convert
12917     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
12918     # registers except esp clobbered at this point
12919     # restore ed
12920     89/<- %edx 4/r32/esp
12921     (flush _test-output-buffered-file)
12922     (flush _test-error-buffered-file)
12923 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
12929     # check output
12930     (check-next-stream-line-equal _test-output-stream "foo:"                            "F - test-convert-write-to-stream/0")
12931     (check-next-stream-line-equal _test-output-stream "  # . prologue"                  "F - test-convert-write-to-stream/1")
12932     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                   "F - test-convert-write-to-stream/2")
12933     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"          "F - test-convert-write-to-stream/3")
12934     (check-next-stream-line-equal _test-output-stream "  {"                             "F - test-convert-write-to-stream/4")
12935     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"           "F - test-convert-write-to-stream/5")
12936     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %esi"        "F - test-convert-write-to-stream/6")
12937     (check-next-stream-line-equal _test-output-stream "    be/copy-to-esi 0/imm32"      "F - test-convert-write-to-stream/7")
12938     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"        "F - test-convert-write-to-stream/8")
12939     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"      "F - test-convert-write-to-stream/9")
12940     (check-next-stream-line-equal _test-output-stream "    (write-to-stream %esi %ecx 0x00000004)"  "F - test-convert-write-to-stream/10")
12941     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-write-to-stream/11")
12942     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %esi"         "F - test-convert-write-to-stream/12")
12943     (check-next-stream-line-equal _test-output-stream "  }"                             "F - test-convert-write-to-stream/13")
12944     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"          "F - test-convert-write-to-stream/14")
12945     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                  "F - test-convert-write-to-stream/15")
12946     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"          "F - test-convert-write-to-stream/16")
12947     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                 "F - test-convert-write-to-stream/17")
12948     (check-next-stream-line-equal _test-output-stream "  c3/return"                     "F - test-convert-write-to-stream/18")
12949     # . epilogue
12950     89/<- %esp 5/r32/ebp
12951     5d/pop-to-ebp
12952     c3/return
12953 
12954 test-convert-write-to-stream-with-correct-payload-size:
12955     # . prologue
12956     55/push-ebp
12957     89/<- %ebp 4/r32/esp
12958     # setup
12959     (clear-stream _test-input-stream)
12960     (clear-stream $_test-input-buffered-file->buffer)
12961     (clear-stream _test-output-stream)
12962     (clear-stream $_test-output-buffered-file->buffer)
12963     #
12964     (write _test-input-stream "fn foo {\n")
12965     (write _test-input-stream "  var s/esi: (addr stream handle int) <- copy 0\n")
12966     (write _test-input-stream "  var o/ecx: (addr handle int) <- copy 0\n")
12967     (write _test-input-stream "  write-to-stream s, o\n")
12968     (write _test-input-stream "}\n")
12969     # convert
12970     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
12971     # registers except esp clobbered at this point
12972     # restore ed
12973     89/<- %edx 4/r32/esp
12974     (flush _test-output-buffered-file)
12975     (flush _test-error-buffered-file)
12976 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
12982     # check output
12983     (check-next-stream-line-equal _test-output-stream "foo:"                            "F - test-convert-write-to-stream-with-correct-payload-size/0")
12984     (check-next-stream-line-equal _test-output-stream "  # . prologue"                  "F - test-convert-write-to-stream-with-correct-payload-size/1")
12985     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                   "F - test-convert-write-to-stream-with-correct-payload-size/2")
12986     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"          "F - test-convert-write-to-stream-with-correct-payload-size/3")
12987     (check-next-stream-line-equal _test-output-stream "  {"                             "F - test-convert-write-to-stream-with-correct-payload-size/4")
12988     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"           "F - test-convert-write-to-stream-with-correct-payload-size/5")
12989     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %esi"        "F - test-convert-write-to-stream-with-correct-payload-size/6")
12990     (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")
12991     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"        "F - test-convert-write-to-stream-with-correct-payload-size/8")
12992     (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")
12993     (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")
12994     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-write-to-stream-with-correct-payload-size/11")
12995     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %esi"         "F - test-convert-write-to-stream-with-correct-payload-size/12")
12996     (check-next-stream-line-equal _test-output-stream "  }"                             "F - test-convert-write-to-stream-with-correct-payload-size/13")
12997     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"          "F - test-convert-write-to-stream-with-correct-payload-size/14")
12998     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                  "F - test-convert-write-to-stream-with-correct-payload-size/15")
12999     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"          "F - test-convert-write-to-stream-with-correct-payload-size/16")
13000     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                 "F - test-convert-write-to-stream-with-correct-payload-size/17")
13001     (check-next-stream-line-equal _test-output-stream "  c3/return"                     "F - test-convert-write-to-stream-with-correct-payload-size/18")
13002     # . epilogue
13003     89/<- %esp 5/r32/ebp
13004     5d/pop-to-ebp
13005     c3/return
13006 
13007 test-write-to-stream-with-non-stream-atom-base-type:
13008     # . prologue
13009     55/push-ebp
13010     89/<- %ebp 4/r32/esp
13011     # setup
13012     (clear-stream _test-input-stream)
13013     (clear-stream $_test-input-buffered-file->buffer)
13014     (clear-stream _test-output-stream)
13015     (clear-stream $_test-output-buffered-file->buffer)
13016     (clear-stream _test-error-stream)
13017     (clear-stream $_test-error-buffered-file->buffer)
13018     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13019     68/push 0/imm32
13020     68/push 0/imm32
13021     89/<- %edx 4/r32/esp
13022     (tailor-exit-descriptor %edx 0x10)
13023     #
13024     (write _test-input-stream "fn foo {\n")
13025     (write _test-input-stream "  var a: int\n")
13026     (write _test-input-stream "  write-to-stream a, 0\n")
13027     (write _test-input-stream "}\n")
13028     # convert
13029     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13030     # registers except esp clobbered at this point
13031     # restore ed
13032     89/<- %edx 4/r32/esp
13033     (flush _test-output-buffered-file)
13034     (flush _test-error-buffered-file)
13035 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13041     # check output
13042     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-non-stream-atom-base-type: output should be empty")
13043     (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")
13044     # check that stop(1) was called
13045     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-non-stream-atom-base-type: exit status")
13046     # don't restore from ebp
13047     81 0/subop/add %esp 8/imm32
13048     # . epilogue
13049     5d/pop-to-ebp
13050     c3/return
13051 
13052 test-write-to-stream-with-non-stream-compound-base-type:
13053     # . prologue
13054     55/push-ebp
13055     89/<- %ebp 4/r32/esp
13056     # setup
13057     (clear-stream _test-input-stream)
13058     (clear-stream $_test-input-buffered-file->buffer)
13059     (clear-stream _test-output-stream)
13060     (clear-stream $_test-output-buffered-file->buffer)
13061     (clear-stream _test-error-stream)
13062     (clear-stream $_test-error-buffered-file->buffer)
13063     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13064     68/push 0/imm32
13065     68/push 0/imm32
13066     89/<- %edx 4/r32/esp
13067     (tailor-exit-descriptor %edx 0x10)
13068     #
13069     (write _test-input-stream "fn foo {\n")
13070     (write _test-input-stream "  var a: (handle int)\n")
13071     (write _test-input-stream "  write-to-stream a, 0\n")
13072     (write _test-input-stream "}\n")
13073     # convert
13074     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13075     # registers except esp clobbered at this point
13076     # restore ed
13077     89/<- %edx 4/r32/esp
13078     (flush _test-output-buffered-file)
13079     (flush _test-error-buffered-file)
13080 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13086     # check output
13087     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-non-stream-compound-base-type: output should be empty")
13088     (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")
13089     # check that stop(1) was called
13090     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-non-stream-compound-base-type: exit status")
13091     # don't restore from ebp
13092     81 0/subop/add %esp 8/imm32
13093     # . epilogue
13094     5d/pop-to-ebp
13095     c3/return
13096 
13097 test-write-to-stream-with-non-stream-compound-base-type-2:
13098     # . prologue
13099     55/push-ebp
13100     89/<- %ebp 4/r32/esp
13101     # setup
13102     (clear-stream _test-input-stream)
13103     (clear-stream $_test-input-buffered-file->buffer)
13104     (clear-stream _test-output-stream)
13105     (clear-stream $_test-output-buffered-file->buffer)
13106     (clear-stream _test-error-stream)
13107     (clear-stream $_test-error-buffered-file->buffer)
13108     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13109     68/push 0/imm32
13110     68/push 0/imm32
13111     89/<- %edx 4/r32/esp
13112     (tailor-exit-descriptor %edx 0x10)
13113     #
13114     (write _test-input-stream "fn foo {\n")
13115     (write _test-input-stream "  var a: (addr int)\n")
13116     (write _test-input-stream "  write-to-stream a, 0\n")
13117     (write _test-input-stream "}\n")
13118     # convert
13119     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13120     # registers except esp clobbered at this point
13121     # restore ed
13122     89/<- %edx 4/r32/esp
13123     (flush _test-output-buffered-file)
13124     (flush _test-error-buffered-file)
13125 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13131     # check output
13132     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-non-stream-compound-base-type-2: output should be empty")
13133     (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")
13134     # check that stop(1) was called
13135     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-non-stream-compound-base-type-2: exit status")
13136     # don't restore from ebp
13137     81 0/subop/add %esp 8/imm32
13138     # . epilogue
13139     5d/pop-to-ebp
13140     c3/return
13141 
13142 test-write-to-stream-with-stream-atom-base-type:
13143     # . prologue
13144     55/push-ebp
13145     89/<- %ebp 4/r32/esp
13146     # setup
13147     (clear-stream _test-input-stream)
13148     (clear-stream $_test-input-buffered-file->buffer)
13149     (clear-stream _test-output-stream)
13150     (clear-stream $_test-output-buffered-file->buffer)
13151     (clear-stream _test-error-stream)
13152     (clear-stream $_test-error-buffered-file->buffer)
13153     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13154     68/push 0/imm32
13155     68/push 0/imm32
13156     89/<- %edx 4/r32/esp
13157     (tailor-exit-descriptor %edx 0x10)
13158     #
13159     (write _test-input-stream "fn foo {\n")
13160     (write _test-input-stream "  var a: stream\n")
13161     (write _test-input-stream "  write-to-stream a, 0\n")
13162     (write _test-input-stream "}\n")
13163     # convert
13164     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13165     # registers except esp clobbered at this point
13166     # restore ed
13167     89/<- %edx 4/r32/esp
13168     (flush _test-output-buffered-file)
13169     (flush _test-error-buffered-file)
13170 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13176     # check output
13177     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-stream-atom-base-type: output should be empty")
13178     (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")
13179     # check that stop(1) was called
13180     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-stream-atom-base-type: exit status")
13181     # don't restore from ebp
13182     81 0/subop/add %esp 8/imm32
13183     # . epilogue
13184     5d/pop-to-ebp
13185     c3/return
13186 
13187 test-write-to-stream-with-wrong-index-type:
13188     # . prologue
13189     55/push-ebp
13190     89/<- %ebp 4/r32/esp
13191     # setup
13192     (clear-stream _test-input-stream)
13193     (clear-stream $_test-input-buffered-file->buffer)
13194     (clear-stream _test-output-stream)
13195     (clear-stream $_test-output-buffered-file->buffer)
13196     (clear-stream _test-error-stream)
13197     (clear-stream $_test-error-buffered-file->buffer)
13198     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13199     68/push 0/imm32
13200     68/push 0/imm32
13201     89/<- %edx 4/r32/esp
13202     (tailor-exit-descriptor %edx 0x10)
13203     #
13204     (write _test-input-stream "fn foo {\n")
13205     (write _test-input-stream "  var a/eax: (addr stream int) <- copy 0\n")
13206     (write _test-input-stream "  var b: boolean\n")
13207     (write _test-input-stream "  write-to-stream a, b\n")
13208     (write _test-input-stream "}\n")
13209     # convert
13210     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13211     # registers except esp clobbered at this point
13212     # restore ed
13213     89/<- %edx 4/r32/esp
13214     (flush _test-output-buffered-file)
13215     (flush _test-error-buffered-file)
13216 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13222     # check output
13223     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-wrong-index-type: output should be empty")
13224     (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")
13225     # check that stop(1) was called
13226     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-wrong-index-type: exit status")
13227     # don't restore from ebp
13228     81 0/subop/add %esp 8/imm32
13229     # . epilogue
13230     5d/pop-to-ebp
13231     c3/return
13232 
13233 test-write-to-stream-with-no-inouts:
13234     # . prologue
13235     55/push-ebp
13236     89/<- %ebp 4/r32/esp
13237     # setup
13238     (clear-stream _test-input-stream)
13239     (clear-stream $_test-input-buffered-file->buffer)
13240     (clear-stream _test-output-stream)
13241     (clear-stream $_test-output-buffered-file->buffer)
13242     (clear-stream _test-error-stream)
13243     (clear-stream $_test-error-buffered-file->buffer)
13244     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13245     68/push 0/imm32
13246     68/push 0/imm32
13247     89/<- %edx 4/r32/esp
13248     (tailor-exit-descriptor %edx 0x10)
13249     #
13250     (write _test-input-stream "fn foo {\n")
13251     (write _test-input-stream "  write-to-stream\n")
13252     (write _test-input-stream "}\n")
13253     # convert
13254     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13255     # registers except esp clobbered at this point
13256     # restore ed
13257     89/<- %edx 4/r32/esp
13258     (flush _test-output-buffered-file)
13259     (flush _test-error-buffered-file)
13260 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13266     # check output
13267     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-no-inouts: output should be empty")
13268     (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")
13269     # check that stop(1) was called
13270     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-no-inouts: exit status")
13271     # don't restore from ebp
13272     81 0/subop/add %esp 8/imm32
13273     # . epilogue
13274     5d/pop-to-ebp
13275     c3/return
13276 
13277 test-write-to-stream-with-too-few-inouts:
13278     # . prologue
13279     55/push-ebp
13280     89/<- %ebp 4/r32/esp
13281     # setup
13282     (clear-stream _test-input-stream)
13283     (clear-stream $_test-input-buffered-file->buffer)
13284     (clear-stream _test-output-stream)
13285     (clear-stream $_test-output-buffered-file->buffer)
13286     (clear-stream _test-error-stream)
13287     (clear-stream $_test-error-buffered-file->buffer)
13288     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13289     68/push 0/imm32
13290     68/push 0/imm32
13291     89/<- %edx 4/r32/esp
13292     (tailor-exit-descriptor %edx 0x10)
13293     #
13294     (write _test-input-stream "fn foo {\n")
13295     (write _test-input-stream "  var a: (addr stream int)\n")
13296     (write _test-input-stream "  write-to-stream a\n")
13297     (write _test-input-stream "}\n")
13298     # convert
13299     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13300     # registers except esp clobbered at this point
13301     # restore ed
13302     89/<- %edx 4/r32/esp
13303     (flush _test-output-buffered-file)
13304     (flush _test-error-buffered-file)
13305 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13311     # check output
13312     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-too-few-inouts: output should be empty")
13313     (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")
13314     # check that stop(1) was called
13315     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-too-few-inouts: exit status")
13316     # don't restore from ebp
13317     81 0/subop/add %esp 8/imm32
13318     # . epilogue
13319     5d/pop-to-ebp
13320     c3/return
13321 
13322 test-write-to-stream-with-too-many-inouts:
13323     # . prologue
13324     55/push-ebp
13325     89/<- %ebp 4/r32/esp
13326     # setup
13327     (clear-stream _test-input-stream)
13328     (clear-stream $_test-input-buffered-file->buffer)
13329     (clear-stream _test-output-stream)
13330     (clear-stream $_test-output-buffered-file->buffer)
13331     (clear-stream _test-error-stream)
13332     (clear-stream $_test-error-buffered-file->buffer)
13333     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13334     68/push 0/imm32
13335     68/push 0/imm32
13336     89/<- %edx 4/r32/esp
13337     (tailor-exit-descriptor %edx 0x10)
13338     #
13339     (write _test-input-stream "fn foo {\n")
13340     (write _test-input-stream "  var a: (addr stream int)\n")
13341     (write _test-input-stream "  var b: (addr int)\n")
13342     (write _test-input-stream "  write-to-stream a, b, 0\n")
13343     (write _test-input-stream "}\n")
13344     # convert
13345     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13346     # registers except esp clobbered at this point
13347     # restore ed
13348     89/<- %edx 4/r32/esp
13349     (flush _test-output-buffered-file)
13350     (flush _test-error-buffered-file)
13351 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13357     # check output
13358     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-too-many-inouts: output should be empty")
13359     (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")
13360     # check that stop(1) was called
13361     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-too-many-inouts: exit status")
13362     # don't restore from ebp
13363     81 0/subop/add %esp 8/imm32
13364     # . epilogue
13365     5d/pop-to-ebp
13366     c3/return
13367 
13368 test-write-to-stream-with-output:
13369     # . prologue
13370     55/push-ebp
13371     89/<- %ebp 4/r32/esp
13372     # setup
13373     (clear-stream _test-input-stream)
13374     (clear-stream $_test-input-buffered-file->buffer)
13375     (clear-stream _test-output-stream)
13376     (clear-stream $_test-output-buffered-file->buffer)
13377     (clear-stream _test-error-stream)
13378     (clear-stream $_test-error-buffered-file->buffer)
13379     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13380     68/push 0/imm32
13381     68/push 0/imm32
13382     89/<- %edx 4/r32/esp
13383     (tailor-exit-descriptor %edx 0x10)
13384     #
13385     (write _test-input-stream "fn foo {\n")
13386     (write _test-input-stream "  var a: (addr stream int)\n")
13387     (write _test-input-stream "  var b/eax: (addr int) <- copy 0\n")
13388     (write _test-input-stream "  b <- write-to-stream a, b\n")
13389     (write _test-input-stream "}\n")
13390     # convert
13391     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13392     # registers except esp clobbered at this point
13393     # restore ed
13394     89/<- %edx 4/r32/esp
13395     (flush _test-output-buffered-file)
13396     (flush _test-error-buffered-file)
13397 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13403     # check output
13404     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-output: output should be empty")
13405     (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")
13406     # check that stop(1) was called
13407     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-output: exit status")
13408     # don't restore from ebp
13409     81 0/subop/add %esp 8/imm32
13410     # . epilogue
13411     5d/pop-to-ebp
13412     c3/return
13413 
13414 test-length-with-non-array-atom-base-type:
13415     # . prologue
13416     55/push-ebp
13417     89/<- %ebp 4/r32/esp
13418     # setup
13419     (clear-stream _test-input-stream)
13420     (clear-stream $_test-input-buffered-file->buffer)
13421     (clear-stream _test-output-stream)
13422     (clear-stream $_test-output-buffered-file->buffer)
13423     (clear-stream _test-error-stream)
13424     (clear-stream $_test-error-buffered-file->buffer)
13425     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13426     68/push 0/imm32
13427     68/push 0/imm32
13428     89/<- %edx 4/r32/esp
13429     (tailor-exit-descriptor %edx 0x10)
13430     #
13431     (write _test-input-stream "fn foo {\n")
13432     (write _test-input-stream "  var a: int\n")
13433     (write _test-input-stream "  var c/ecx: int <- length a\n")
13434     (write _test-input-stream "}\n")
13435     # convert
13436     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13437     # registers except esp clobbered at this point
13438     # restore ed
13439     89/<- %edx 4/r32/esp
13440     (flush _test-output-buffered-file)
13441     (flush _test-error-buffered-file)
13442 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13448     # check output
13449     (check-stream-equal _test-output-stream  ""  "F - test-length-with-non-array-atom-base-type: output should be empty")
13450     (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")
13451     # check that stop(1) was called
13452     (check-ints-equal *(edx+4) 2 "F - test-length-with-non-array-atom-base-type: exit status")
13453     # don't restore from ebp
13454     81 0/subop/add %esp 8/imm32
13455     # . epilogue
13456     5d/pop-to-ebp
13457     c3/return
13458 
13459 test-length-with-non-array-compound-base-type:
13460     # . prologue
13461     55/push-ebp
13462     89/<- %ebp 4/r32/esp
13463     # setup
13464     (clear-stream _test-input-stream)
13465     (clear-stream $_test-input-buffered-file->buffer)
13466     (clear-stream _test-output-stream)
13467     (clear-stream $_test-output-buffered-file->buffer)
13468     (clear-stream _test-error-stream)
13469     (clear-stream $_test-error-buffered-file->buffer)
13470     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13471     68/push 0/imm32
13472     68/push 0/imm32
13473     89/<- %edx 4/r32/esp
13474     (tailor-exit-descriptor %edx 0x10)
13475     #
13476     (write _test-input-stream "fn foo {\n")
13477     (write _test-input-stream "  var a: (handle int)\n")
13478     (write _test-input-stream "  var c/ecx: (addr int) <- length a, 0\n")
13479     (write _test-input-stream "}\n")
13480     # convert
13481     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13482     # registers except esp clobbered at this point
13483     # restore ed
13484     89/<- %edx 4/r32/esp
13485     (flush _test-output-buffered-file)
13486     (flush _test-error-buffered-file)
13487 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13493     # check output
13494     (check-stream-equal _test-output-stream  ""  "F - test-length-with-non-array-compound-base-type: output should be empty")
13495     (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")
13496     # check that stop(1) was called
13497     (check-ints-equal *(edx+4) 2 "F - test-length-with-non-array-compound-base-type: exit status")
13498     # don't restore from ebp
13499     81 0/subop/add %esp 8/imm32
13500     # . epilogue
13501     5d/pop-to-ebp
13502     c3/return
13503 
13504 test-length-with-non-array-compound-base-type-2:
13505     # . prologue
13506     55/push-ebp
13507     89/<- %ebp 4/r32/esp
13508     # setup
13509     (clear-stream _test-input-stream)
13510     (clear-stream $_test-input-buffered-file->buffer)
13511     (clear-stream _test-output-stream)
13512     (clear-stream $_test-output-buffered-file->buffer)
13513     (clear-stream _test-error-stream)
13514     (clear-stream $_test-error-buffered-file->buffer)
13515     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13516     68/push 0/imm32
13517     68/push 0/imm32
13518     89/<- %edx 4/r32/esp
13519     (tailor-exit-descriptor %edx 0x10)
13520     #
13521     (write _test-input-stream "fn foo {\n")
13522     (write _test-input-stream "  var a: (addr int)\n")
13523     (write _test-input-stream "  var c/ecx: (addr int) <- length a, 0\n")
13524     (write _test-input-stream "}\n")
13525     # convert
13526     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13527     # registers except esp clobbered at this point
13528     # restore ed
13529     89/<- %edx 4/r32/esp
13530     (flush _test-output-buffered-file)
13531     (flush _test-error-buffered-file)
13532 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13538     # check output
13539     (check-stream-equal _test-output-stream  ""  "F - test-length-with-non-array-compound-base-type-2: output should be empty")
13540     (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")
13541     # check that stop(1) was called
13542     (check-ints-equal *(edx+4) 2 "F - test-length-with-non-array-compound-base-type-2: exit status")
13543     # don't restore from ebp
13544     81 0/subop/add %esp 8/imm32
13545     # . epilogue
13546     5d/pop-to-ebp
13547     c3/return
13548 
13549 test-length-with-array-atom-base-type:
13550     # . prologue
13551     55/push-ebp
13552     89/<- %ebp 4/r32/esp
13553     # setup
13554     (clear-stream _test-input-stream)
13555     (clear-stream $_test-input-buffered-file->buffer)
13556     (clear-stream _test-output-stream)
13557     (clear-stream $_test-output-buffered-file->buffer)
13558     (clear-stream _test-error-stream)
13559     (clear-stream $_test-error-buffered-file->buffer)
13560     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13561     68/push 0/imm32
13562     68/push 0/imm32
13563     89/<- %edx 4/r32/esp
13564     (tailor-exit-descriptor %edx 0x10)
13565     #
13566     (write _test-input-stream "fn foo {\n")
13567     (write _test-input-stream "  var a: array\n")
13568     (write _test-input-stream "  var c/ecx: (addr int) <- length a\n")
13569     (write _test-input-stream "}\n")
13570     # convert
13571     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13572     # registers except esp clobbered at this point
13573     # restore ed
13574     89/<- %edx 4/r32/esp
13575     (flush _test-output-buffered-file)
13576     (flush _test-error-buffered-file)
13577 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13583     # check output
13584     (check-stream-equal _test-output-stream  ""  "F - test-length-with-array-atom-base-type: output should be empty")
13585     (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")
13586     # check that stop(1) was called
13587     (check-ints-equal *(edx+4) 2 "F - test-length-with-array-atom-base-type: exit status")
13588     # don't restore from ebp
13589     81 0/subop/add %esp 8/imm32
13590     # . epilogue
13591     5d/pop-to-ebp
13592     c3/return
13593 
13594 test-length-with-addr-base-on-stack:
13595     # . prologue
13596     55/push-ebp
13597     89/<- %ebp 4/r32/esp
13598     # setup
13599     (clear-stream _test-input-stream)
13600     (clear-stream $_test-input-buffered-file->buffer)
13601     (clear-stream _test-output-stream)
13602     (clear-stream $_test-output-buffered-file->buffer)
13603     (clear-stream _test-error-stream)
13604     (clear-stream $_test-error-buffered-file->buffer)
13605     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13606     68/push 0/imm32
13607     68/push 0/imm32
13608     89/<- %edx 4/r32/esp
13609     (tailor-exit-descriptor %edx 0x10)
13610     #
13611     (write _test-input-stream "fn foo {\n")
13612     (write _test-input-stream "  var a: (addr array int)\n")
13613     (write _test-input-stream "  var c/ecx: (addr int) <- length a\n")
13614     (write _test-input-stream "}\n")
13615     # convert
13616     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13617     # registers except esp clobbered at this point
13618     # restore ed
13619     89/<- %edx 4/r32/esp
13620     (flush _test-output-buffered-file)
13621     (flush _test-error-buffered-file)
13622 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13628     # check output
13629     (check-stream-equal _test-output-stream  ""  "F - test-length-with-addr-base-on-stack: output should be empty")
13630     (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")
13631     # check that stop(1) was called
13632     (check-ints-equal *(edx+4) 2 "F - test-length-with-addr-base-on-stack: exit status")
13633     # don't restore from ebp
13634     81 0/subop/add %esp 8/imm32
13635     # . epilogue
13636     5d/pop-to-ebp
13637     c3/return
13638 
13639 test-length-with-wrong-output-type:
13640     # . prologue
13641     55/push-ebp
13642     89/<- %ebp 4/r32/esp
13643     # setup
13644     (clear-stream _test-input-stream)
13645     (clear-stream $_test-input-buffered-file->buffer)
13646     (clear-stream _test-output-stream)
13647     (clear-stream $_test-output-buffered-file->buffer)
13648     (clear-stream _test-error-stream)
13649     (clear-stream $_test-error-buffered-file->buffer)
13650     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13651     68/push 0/imm32
13652     68/push 0/imm32
13653     89/<- %edx 4/r32/esp
13654     (tailor-exit-descriptor %edx 0x10)
13655     #
13656     (write _test-input-stream "fn foo {\n")
13657     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
13658     (write _test-input-stream "  var o/edi: (addr int) <- length a\n")
13659     (write _test-input-stream "}\n")
13660     # convert
13661     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13662     # registers except esp clobbered at this point
13663     # restore ed
13664     89/<- %edx 4/r32/esp
13665     (flush _test-output-buffered-file)
13666     (flush _test-error-buffered-file)
13667 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13673     # check output
13674     (check-stream-equal _test-output-stream  ""  "F - test-length-with-wrong-output-type: output should be empty")
13675     (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")
13676     # check that stop(1) was called
13677     (check-ints-equal *(edx+4) 2 "F - test-length-with-wrong-output-type: exit status")
13678     # don't restore from ebp
13679     81 0/subop/add %esp 8/imm32
13680     # . epilogue
13681     5d/pop-to-ebp
13682     c3/return
13683 
13684 test-length-with-wrong-output-compound-type:
13685     # . prologue
13686     55/push-ebp
13687     89/<- %ebp 4/r32/esp
13688     # setup
13689     (clear-stream _test-input-stream)
13690     (clear-stream $_test-input-buffered-file->buffer)
13691     (clear-stream _test-output-stream)
13692     (clear-stream $_test-output-buffered-file->buffer)
13693     (clear-stream _test-error-stream)
13694     (clear-stream $_test-error-buffered-file->buffer)
13695     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13696     68/push 0/imm32
13697     68/push 0/imm32
13698     89/<- %edx 4/r32/esp
13699     (tailor-exit-descriptor %edx 0x10)
13700     #
13701     (write _test-input-stream "fn foo {\n")
13702     (write _test-input-stream "  var a/ebx: (addr array handle boolean) <- copy 0\n")
13703     (write _test-input-stream "  var o/edi: (addr handle int) <- length a\n")
13704     (write _test-input-stream "}\n")
13705     # convert
13706     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13707     # registers except esp clobbered at this point
13708     # restore ed
13709     89/<- %edx 4/r32/esp
13710     (flush _test-output-buffered-file)
13711     (flush _test-error-buffered-file)
13712 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13718     # check output
13719     (check-stream-equal _test-output-stream  ""  "F - test-length-with-wrong-output-compound-type: output should be empty")
13720     (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")
13721     # check that stop(1) was called
13722     (check-ints-equal *(edx+4) 2 "F - test-length-with-wrong-output-compound-type: exit status")
13723     # don't restore from ebp
13724     81 0/subop/add %esp 8/imm32
13725     # . epilogue
13726     5d/pop-to-ebp
13727     c3/return
13728 
13729 test-length-with-no-inouts:
13730     # . prologue
13731     55/push-ebp
13732     89/<- %ebp 4/r32/esp
13733     # setup
13734     (clear-stream _test-input-stream)
13735     (clear-stream $_test-input-buffered-file->buffer)
13736     (clear-stream _test-output-stream)
13737     (clear-stream $_test-output-buffered-file->buffer)
13738     (clear-stream _test-error-stream)
13739     (clear-stream $_test-error-buffered-file->buffer)
13740     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13741     68/push 0/imm32
13742     68/push 0/imm32
13743     89/<- %edx 4/r32/esp
13744     (tailor-exit-descriptor %edx 0x10)
13745     #
13746     (write _test-input-stream "fn foo {\n")
13747     (write _test-input-stream "  var c/ecx: int <- length\n")
13748     (write _test-input-stream "}\n")
13749     # convert
13750     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13751     # registers except esp clobbered at this point
13752     # restore ed
13753     89/<- %edx 4/r32/esp
13754     (flush _test-output-buffered-file)
13755     (flush _test-error-buffered-file)
13756 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13762     # check output
13763     (check-stream-equal _test-output-stream  ""  "F - test-length-with-no-inouts: output should be empty")
13764     (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")
13765     # check that stop(1) was called
13766     (check-ints-equal *(edx+4) 2 "F - test-length-with-no-inouts: exit status")
13767     # don't restore from ebp
13768     81 0/subop/add %esp 8/imm32
13769     # . epilogue
13770     5d/pop-to-ebp
13771     c3/return
13772 
13773 test-length-with-too-many-inouts:
13774     # . prologue
13775     55/push-ebp
13776     89/<- %ebp 4/r32/esp
13777     # setup
13778     (clear-stream _test-input-stream)
13779     (clear-stream $_test-input-buffered-file->buffer)
13780     (clear-stream _test-output-stream)
13781     (clear-stream $_test-output-buffered-file->buffer)
13782     (clear-stream _test-error-stream)
13783     (clear-stream $_test-error-buffered-file->buffer)
13784     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13785     68/push 0/imm32
13786     68/push 0/imm32
13787     89/<- %edx 4/r32/esp
13788     (tailor-exit-descriptor %edx 0x10)
13789     #
13790     (write _test-input-stream "fn foo {\n")
13791     (write _test-input-stream "  var a: (array int 3)\n")
13792     (write _test-input-stream "  var c/ecx: int <- length a, 0, 0\n")
13793     (write _test-input-stream "}\n")
13794     # convert
13795     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13796     # registers except esp clobbered at this point
13797     # restore ed
13798     89/<- %edx 4/r32/esp
13799     (flush _test-output-buffered-file)
13800     (flush _test-error-buffered-file)
13801 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13807     # check output
13808     (check-stream-equal _test-output-stream  ""  "F - test-length-with-too-many-inouts: output should be empty")
13809     (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")
13810     # check that stop(1) was called
13811     (check-ints-equal *(edx+4) 2 "F - test-length-with-too-many-inouts: exit status")
13812     # don't restore from ebp
13813     81 0/subop/add %esp 8/imm32
13814     # . epilogue
13815     5d/pop-to-ebp
13816     c3/return
13817 
13818 test-length-with-no-output:
13819     # . prologue
13820     55/push-ebp
13821     89/<- %ebp 4/r32/esp
13822     # setup
13823     (clear-stream _test-input-stream)
13824     (clear-stream $_test-input-buffered-file->buffer)
13825     (clear-stream _test-output-stream)
13826     (clear-stream $_test-output-buffered-file->buffer)
13827     (clear-stream _test-error-stream)
13828     (clear-stream $_test-error-buffered-file->buffer)
13829     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13830     68/push 0/imm32
13831     68/push 0/imm32
13832     89/<- %edx 4/r32/esp
13833     (tailor-exit-descriptor %edx 0x10)
13834     #
13835     (write _test-input-stream "fn foo {\n")
13836     (write _test-input-stream "  var a: (array int 3)\n")
13837     (write _test-input-stream "  length a\n")
13838     (write _test-input-stream "}\n")
13839     # convert
13840     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13841     # registers except esp clobbered at this point
13842     # restore ed
13843     89/<- %edx 4/r32/esp
13844     (flush _test-output-buffered-file)
13845     (flush _test-error-buffered-file)
13846 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13852     # check output
13853     (check-stream-equal _test-output-stream  ""  "F - test-length-with-no-output: output should be empty")
13854     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt length: must have an output"  "F - test-length-with-no-output: error message")
13855     # check that stop(1) was called
13856     (check-ints-equal *(edx+4) 2 "F - test-length-with-no-output: exit status")
13857     # don't restore from ebp
13858     81 0/subop/add %esp 8/imm32
13859     # . epilogue
13860     5d/pop-to-ebp
13861     c3/return
13862 
13863 test-length-with-too-many-outputs:
13864     # . prologue
13865     55/push-ebp
13866     89/<- %ebp 4/r32/esp
13867     # setup
13868     (clear-stream _test-input-stream)
13869     (clear-stream $_test-input-buffered-file->buffer)
13870     (clear-stream _test-output-stream)
13871     (clear-stream $_test-output-buffered-file->buffer)
13872     (clear-stream _test-error-stream)
13873     (clear-stream $_test-error-buffered-file->buffer)
13874     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13875     68/push 0/imm32
13876     68/push 0/imm32
13877     89/<- %edx 4/r32/esp
13878     (tailor-exit-descriptor %edx 0x10)
13879     #
13880     (write _test-input-stream "fn foo {\n")
13881     (write _test-input-stream "  var a: (array int 3)\n")
13882     (write _test-input-stream "  var b/eax: int <- copy 0\n")
13883     (write _test-input-stream "  var c/ecx: int <- copy 0\n")
13884     (write _test-input-stream "  b, c <- length a\n")
13885     (write _test-input-stream "}\n")
13886     # convert
13887     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13888     # registers except esp clobbered at this point
13889     # restore ed
13890     89/<- %edx 4/r32/esp
13891     (flush _test-output-buffered-file)
13892     (flush _test-error-buffered-file)
13893 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13899     # check output
13900     (check-stream-equal _test-output-stream  ""  "F - test-length-with-too-many-outputs: output should be empty")
13901     (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")
13902     # check that stop(1) was called
13903     (check-ints-equal *(edx+4) 2 "F - test-length-with-too-many-outputs: exit status")
13904     # don't restore from ebp
13905     81 0/subop/add %esp 8/imm32
13906     # . epilogue
13907     5d/pop-to-ebp
13908     c3/return
13909 
13910 test-convert-function-with-return-register-and-local:
13911     # . prologue
13912     55/push-ebp
13913     89/<- %ebp 4/r32/esp
13914     # setup
13915     (clear-stream _test-input-stream)
13916     (clear-stream $_test-input-buffered-file->buffer)
13917     (clear-stream _test-output-stream)
13918     (clear-stream $_test-output-buffered-file->buffer)
13919     #
13920     (write _test-input-stream "fn foo -> _/eax: int {\n")
13921     (write _test-input-stream "  var y/eax: int <- copy 3\n")
13922     (write _test-input-stream "  var z/ecx: int <- copy 4\n")
13923     (write _test-input-stream "  return y\n")
13924     (write _test-input-stream "}\n")
13925     # convert
13926     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
13927     (flush _test-output-buffered-file)
13928 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
13934     # check output
13935     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-register-and-local/0")
13936     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-register-and-local/1")
13937     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-register-and-local/2")
13938     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-register-and-local/3")
13939     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-register-and-local/4")
13940     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-register-and-local/5")
13941     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-with-return-register-and-local/6")
13942     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 3/imm32"  "F - test-convert-function-with-return-register-and-local/7")
13943     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-return-register-and-local/8")
13944     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 4/imm32"  "F - test-convert-function-with-return-register-and-local/9")
13945     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32" "F - test-convert-function-with-return-register-and-local/10")
13946     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-function-with-return-register-and-local/11")
13947     (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")
13948     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-register-and-local/13")
13949     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-register-and-local/14")
13950     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-register-and-local/15")
13951     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-register-and-local/16")
13952     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-register-and-local/17")
13953     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-register-and-local/18")
13954     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-register-and-local/19")
13955     # . epilogue
13956     89/<- %esp 5/r32/ebp
13957     5d/pop-to-ebp
13958     c3/return
13959 
13960 test-convert-function-with-return-register-and-local-2:
13961     # . prologue
13962     55/push-ebp
13963     89/<- %ebp 4/r32/esp
13964     # setup
13965     (clear-stream _test-input-stream)
13966     (clear-stream $_test-input-buffered-file->buffer)
13967     (clear-stream _test-output-stream)
13968     (clear-stream $_test-output-buffered-file->buffer)
13969     #
13970     (write _test-input-stream "fn foo -> _/eax: int {\n")
13971     (write _test-input-stream "  var y/eax: int <- copy 3\n")
13972     (write _test-input-stream "  var z/ecx: int <- copy 4\n")
13973     (write _test-input-stream "  return z\n")
13974     (write _test-input-stream "}\n")
13975     # convert
13976     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
13977     (flush _test-output-buffered-file)
13978 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
13984     # check output
13985     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-register-and-local-2/0")
13986     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-register-and-local-2/1")
13987     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-register-and-local-2/2")
13988     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-register-and-local-2/3")
13989     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-register-and-local-2/4")
13990     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-register-and-local-2/5")
13991     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-with-return-register-and-local-2/6")
13992     (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")
13993     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-return-register-and-local-2/8")
13994     (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")
13995     (check-next-stream-line-equal _test-output-stream "    8b/-> %ecx 0x00000000/r32" "F - test-convert-function-with-return-register-and-local-2/10")
13996     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-function-with-return-register-and-local-2/11")
13997     (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")
13998     (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")
13999     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-register-and-local-2/14")
14000     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-register-and-local-2/15")
14001     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-register-and-local-2/16")
14002     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-register-and-local-2/17")
14003     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-register-and-local-2/18")
14004     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-register-and-local-2/19")
14005     # . epilogue
14006     89/<- %esp 5/r32/ebp
14007     5d/pop-to-ebp
14008     c3/return
14009 
14010 test-convert-function-with-return-float-register-and-local:
14011     # . prologue
14012     55/push-ebp
14013     89/<- %ebp 4/r32/esp
14014     # setup
14015     (clear-stream _test-input-stream)
14016     (clear-stream $_test-input-buffered-file->buffer)
14017     (clear-stream _test-output-stream)
14018     (clear-stream $_test-output-buffered-file->buffer)
14019     #
14020     (write _test-input-stream "fn foo -> _/xmm1: float {\n")
14021     (write _test-input-stream "  var y/eax: int <- copy 3\n")
14022     (write _test-input-stream "  var g/xmm0: float <- convert y\n")
14023     (write _test-input-stream "  var h/xmm1: float <- convert y\n")
14024     (write _test-input-stream "  return g\n")
14025     (write _test-input-stream "}\n")
14026     # convert
14027     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
14028     (flush _test-output-buffered-file)
14029 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
14035     # check output
14036     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-float-register-and-local/0")
14037     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-float-register-and-local/1")
14038     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-float-register-and-local/2")
14039     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-float-register-and-local/3")
14040     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-float-register-and-local/4")
14041     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-float-register-and-local/5")
14042     (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
14043     (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")
14044     (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
14045     (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")
14046     (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")
14047     (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
14048     (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")
14049     (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")
14050     (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
14051     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-floating-point-dereferenced/15")  # reclaim h
14052     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 0/x32"  "F - test-convert-floating-point-dereferenced/16")  # reclaim g
14053     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-floating-point-dereferenced/17")
14054     (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
14055     (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")
14056     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-float-register-and-local/20")
14057     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-float-register-and-local/21")
14058     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-float-register-and-local/22")
14059     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-float-register-and-local/23")
14060     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-float-register-and-local/24")
14061     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-float-register-and-local/25")
14062     # . epilogue
14063     89/<- %esp 5/r32/ebp
14064     5d/pop-to-ebp
14065     c3/return
14066 
14067 test-convert-function-with-return-and-local-vars:
14068     # . prologue
14069     55/push-ebp
14070     89/<- %ebp 4/r32/esp
14071     # setup
14072     (clear-stream _test-input-stream)
14073     (clear-stream $_test-input-buffered-file->buffer)
14074     (clear-stream _test-output-stream)
14075     (clear-stream $_test-output-buffered-file->buffer)
14076     #
14077     (write _test-input-stream "fn foo -> _/eax: int {\n")
14078     (write _test-input-stream "  {\n")
14079     (write _test-input-stream "    var x: int\n")
14080     (write _test-input-stream "    {\n")
14081     (write _test-input-stream "      var y: int\n")
14082     (write _test-input-stream "      return y\n")
14083     (write _test-input-stream "      increment x\n")
14084     (write _test-input-stream "    }\n")
14085     (write _test-input-stream "  }\n")
14086     (write _test-input-stream "  return 0\n")
14087     (write _test-input-stream "}\n")
14088     # convert
14089     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
14090     (flush _test-output-buffered-file)
14091 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
14097     # check output
14098     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-and-local-vars/0")
14099     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-and-local-vars/1")
14100     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-and-local-vars/2")
14101     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-and-local-vars/3")
14102     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-and-local-vars/4")
14103     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-and-local-vars/5")
14104     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-return-and-local-vars/6")
14105     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-return-and-local-vars/7")
14106     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-return-and-local-vars/8")  # var x
14107     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-return-and-local-vars/9")
14108     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-return-and-local-vars/10")
14109     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-return-and-local-vars/11")  # var y
14110     (check-next-stream-line-equal _test-output-stream "        8b/-> *(ebp+0xfffffff8) 0x00000000/r32" "F - test-convert-function-with-return-and-local-vars/12")
14111     (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")
14112     (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")
14113     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-and-local-vars/15")
14114     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-return-and-local-vars/16")
14115     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-return-and-local-vars/17")
14116     (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")
14117     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-return-and-local-vars/19")
14118     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-return-and-local-vars/20")
14119     (check-next-stream-line-equal _test-output-stream "    c7 0/subop/copy %eax 0/imm32"  "F - test-convert-function-with-return-and-local-vars/21")
14120     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-and-local-vars/21")
14121     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-and-local-vars/21")
14122     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-and-local-vars/22")
14123     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-and-local-vars/23")
14124     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-and-local-vars/24")
14125     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-and-local-vars/25")
14126     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-and-local-vars/26")
14127     # . epilogue
14128     89/<- %esp 5/r32/ebp
14129     5d/pop-to-ebp
14130     c3/return
14131 
14132 test-copy-object-with-no-inout:
14133     # . prologue
14134     55/push-ebp
14135     89/<- %ebp 4/r32/esp
14136     # setup
14137     (clear-stream _test-input-stream)
14138     (clear-stream $_test-input-buffered-file->buffer)
14139     (clear-stream _test-output-stream)
14140     (clear-stream $_test-output-buffered-file->buffer)
14141     (clear-stream _test-error-stream)
14142     (clear-stream $_test-error-buffered-file->buffer)
14143     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14144     68/push 0/imm32
14145     68/push 0/imm32
14146     89/<- %edx 4/r32/esp
14147     (tailor-exit-descriptor %edx 0x10)
14148     #
14149     (write _test-input-stream "fn foo {\n")
14150     (write _test-input-stream "  copy-object\n")
14151     (write _test-input-stream "}\n")
14152     # convert
14153     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14154     # registers except esp clobbered at this point
14155     # restore ed
14156     89/<- %edx 4/r32/esp
14157     (flush _test-output-buffered-file)
14158     (flush _test-error-buffered-file)
14159 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14165     # check output
14166     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-with-no-inout: output should be empty")
14167     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-object' must have two inouts"  "F - test-copy-object-with-no-inout: error message")
14168     # check that stop(1) was called
14169     (check-ints-equal *(edx+4) 2 "F - test-copy-object-with-no-inout: exit status")
14170     # don't restore from ebp
14171     81 0/subop/add %esp 8/imm32
14172     # . epilogue
14173     5d/pop-to-ebp
14174     c3/return
14175 
14176 test-copy-object-with-no-source:
14177     # . prologue
14178     55/push-ebp
14179     89/<- %ebp 4/r32/esp
14180     # setup
14181     (clear-stream _test-input-stream)
14182     (clear-stream $_test-input-buffered-file->buffer)
14183     (clear-stream _test-output-stream)
14184     (clear-stream $_test-output-buffered-file->buffer)
14185     (clear-stream _test-error-stream)
14186     (clear-stream $_test-error-buffered-file->buffer)
14187     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14188     68/push 0/imm32
14189     68/push 0/imm32
14190     89/<- %edx 4/r32/esp
14191     (tailor-exit-descriptor %edx 0x10)
14192     #
14193     (write _test-input-stream "fn foo {\n")
14194     (write _test-input-stream "  var x: (addr int)\n")
14195     (write _test-input-stream "  copy-object x\n")
14196     (write _test-input-stream "}\n")
14197     # convert
14198     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14199     # registers except esp clobbered at this point
14200     # restore ed
14201     89/<- %edx 4/r32/esp
14202     (flush _test-output-buffered-file)
14203     (flush _test-error-buffered-file)
14204 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14210     # check output
14211     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-with-no-source: output should be empty")
14212     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-object' must have two inouts"  "F - test-copy-object-with-no-source: error message")
14213     # check that stop(1) was called
14214     (check-ints-equal *(edx+4) 2 "F - test-copy-object-with-no-source: exit status")
14215     # don't restore from ebp
14216     81 0/subop/add %esp 8/imm32
14217     # . epilogue
14218     5d/pop-to-ebp
14219     c3/return
14220 
14221 test-copy-object-with-too-many-inouts:
14222     # . prologue
14223     55/push-ebp
14224     89/<- %ebp 4/r32/esp
14225     # setup
14226     (clear-stream _test-input-stream)
14227     (clear-stream $_test-input-buffered-file->buffer)
14228     (clear-stream _test-output-stream)
14229     (clear-stream $_test-output-buffered-file->buffer)
14230     (clear-stream _test-error-stream)
14231     (clear-stream $_test-error-buffered-file->buffer)
14232     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14233     68/push 0/imm32
14234     68/push 0/imm32
14235     89/<- %edx 4/r32/esp
14236     (tailor-exit-descriptor %edx 0x10)
14237     #
14238     (write _test-input-stream "fn foo {\n")
14239     (write _test-input-stream "  var x: (addr boolean)\n")
14240     (write _test-input-stream "  copy-object x, x, x\n")
14241     (write _test-input-stream "}\n")
14242     # convert
14243     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14244     # registers except esp clobbered at this point
14245     # restore ed
14246     89/<- %edx 4/r32/esp
14247     (flush _test-output-buffered-file)
14248     (flush _test-error-buffered-file)
14249 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14255     # check output
14256     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-with-too-many-inouts: output should be empty")
14257     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-object' must have two inouts"  "F - test-copy-object-with-too-many-inouts: error message")
14258     # check that stop(1) was called
14259     (check-ints-equal *(edx+4) 2 "F - test-copy-object-with-too-many-inouts: exit status")
14260     # don't restore from ebp
14261     81 0/subop/add %esp 8/imm32
14262     # . epilogue
14263     5d/pop-to-ebp
14264     c3/return
14265 
14266 test-copy-object-with-output:
14267     # . prologue
14268     55/push-ebp
14269     89/<- %ebp 4/r32/esp
14270     # setup
14271     (clear-stream _test-input-stream)
14272     (clear-stream $_test-input-buffered-file->buffer)
14273     (clear-stream _test-output-stream)
14274     (clear-stream $_test-output-buffered-file->buffer)
14275     (clear-stream _test-error-stream)
14276     (clear-stream $_test-error-buffered-file->buffer)
14277     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14278     68/push 0/imm32
14279     68/push 0/imm32
14280     89/<- %edx 4/r32/esp
14281     (tailor-exit-descriptor %edx 0x10)
14282     #
14283     (write _test-input-stream "fn foo {\n")
14284     (write _test-input-stream "  var x/eax: (addr boolean) <- copy 0\n")
14285     (write _test-input-stream "  var y/ecx: (addr boolean) <- copy 0\n")
14286     (write _test-input-stream "  x <- copy-object x, y\n")
14287     (write _test-input-stream "}\n")
14288     # convert
14289     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14290     # registers except esp clobbered at this point
14291     # restore ed
14292     89/<- %edx 4/r32/esp
14293     (flush _test-output-buffered-file)
14294     (flush _test-error-buffered-file)
14295 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14301     # check output
14302     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-with-output: output should be empty")
14303     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-object' must not have any outputs"  "F - test-copy-object-with-output: error message")
14304     # check that stop(1) was called
14305     (check-ints-equal *(edx+4) 2 "F - test-copy-object-with-output: exit status")
14306     # don't restore from ebp
14307     81 0/subop/add %esp 8/imm32
14308     # . epilogue
14309     5d/pop-to-ebp
14310     c3/return
14311 
14312 test-copy-object-deref-address:
14313     # . prologue
14314     55/push-ebp
14315     89/<- %ebp 4/r32/esp
14316     # setup
14317     (clear-stream _test-input-stream)
14318     (clear-stream $_test-input-buffered-file->buffer)
14319     (clear-stream _test-output-stream)
14320     (clear-stream $_test-output-buffered-file->buffer)
14321     #
14322     (write _test-input-stream "fn foo {\n")
14323     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
14324     (write _test-input-stream "  var y/ecx: (addr addr int) <- copy 0\n")
14325     (write _test-input-stream "  copy-object *y, x\n")
14326     (write _test-input-stream "}\n")
14327     # convert
14328     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
14329     (flush _test-output-buffered-file)
14330     # no errors
14331     # . epilogue
14332     5d/pop-to-ebp
14333     c3/return
14334 
14335 test-copy-object-non-addr:
14336     # . prologue
14337     55/push-ebp
14338     89/<- %ebp 4/r32/esp
14339     # setup
14340     (clear-stream _test-input-stream)
14341     (clear-stream $_test-input-buffered-file->buffer)
14342     (clear-stream _test-output-stream)
14343     (clear-stream $_test-output-buffered-file->buffer)
14344     (clear-stream _test-error-stream)
14345     (clear-stream $_test-error-buffered-file->buffer)
14346     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14347     68/push 0/imm32
14348     68/push 0/imm32
14349     89/<- %edx 4/r32/esp
14350     (tailor-exit-descriptor %edx 0x10)
14351     #
14352     (write _test-input-stream "fn foo {\n")
14353     (write _test-input-stream "  var x: int\n")
14354     (write _test-input-stream "  var y: int\n")
14355     (write _test-input-stream "  copy-object y, x\n")
14356     (write _test-input-stream "}\n")
14357     # convert
14358     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14359     # registers except esp clobbered at this point
14360     # restore ed
14361     89/<- %edx 4/r32/esp
14362     (flush _test-output-buffered-file)
14363     (flush _test-error-buffered-file)
14364 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14370     # check output
14371     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-non-addr: output should be empty")
14372     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-object: two inouts with identical addr types expected"  "F - test-copy-object-non-addr: error message")
14373     # check that stop(1) was called
14374     (check-ints-equal *(edx+4) 2 "F - test-copy-object-non-addr: exit status")
14375     # don't restore from ebp
14376     81 0/subop/add %esp 8/imm32
14377     # . epilogue
14378     5d/pop-to-ebp
14379     c3/return
14380 
14381 test-copy-object-non-equal:
14382     # . prologue
14383     55/push-ebp
14384     89/<- %ebp 4/r32/esp
14385     # setup
14386     (clear-stream _test-input-stream)
14387     (clear-stream $_test-input-buffered-file->buffer)
14388     (clear-stream _test-output-stream)
14389     (clear-stream $_test-output-buffered-file->buffer)
14390     (clear-stream _test-error-stream)
14391     (clear-stream $_test-error-buffered-file->buffer)
14392     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14393     68/push 0/imm32
14394     68/push 0/imm32
14395     89/<- %edx 4/r32/esp
14396     (tailor-exit-descriptor %edx 0x10)
14397     #
14398     (write _test-input-stream "fn foo {\n")
14399     (write _test-input-stream "  var x: (addr int)\n")
14400     (write _test-input-stream "  var y: (addr boolean)\n")
14401     (write _test-input-stream "  copy-object y, x\n")
14402     (write _test-input-stream "}\n")
14403     # convert
14404     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14405     # registers except esp clobbered at this point
14406     # restore ed
14407     89/<- %edx 4/r32/esp
14408     (flush _test-output-buffered-file)
14409     (flush _test-error-buffered-file)
14410 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14416     # check output
14417     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-non-equal: output should be empty")
14418     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-object: two inouts with identical addr types expected"  "F - test-copy-object-non-equal: error message")
14419     # check that stop(1) was called
14420     (check-ints-equal *(edx+4) 2 "F - test-copy-object-non-equal: exit status")
14421     # don't restore from ebp
14422     81 0/subop/add %esp 8/imm32
14423     # . epilogue
14424     5d/pop-to-ebp
14425     c3/return
14426 
14427 test-allocate-with-no-inout:
14428     # . prologue
14429     55/push-ebp
14430     89/<- %ebp 4/r32/esp
14431     # setup
14432     (clear-stream _test-input-stream)
14433     (clear-stream $_test-input-buffered-file->buffer)
14434     (clear-stream _test-output-stream)
14435     (clear-stream $_test-output-buffered-file->buffer)
14436     (clear-stream _test-error-stream)
14437     (clear-stream $_test-error-buffered-file->buffer)
14438     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14439     68/push 0/imm32
14440     68/push 0/imm32
14441     89/<- %edx 4/r32/esp
14442     (tailor-exit-descriptor %edx 0x10)
14443     #
14444     (write _test-input-stream "fn foo {\n")
14445     (write _test-input-stream "  allocate\n")
14446     (write _test-input-stream "}\n")
14447     # convert
14448     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14449     # registers except esp clobbered at this point
14450     # restore ed
14451     89/<- %edx 4/r32/esp
14452     (flush _test-output-buffered-file)
14453     (flush _test-error-buffered-file)
14454 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14460     # check output
14461     (check-stream-equal _test-output-stream  ""  "F - test-allocate-with-no-inout: output should be empty")
14462     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'allocate' must have a single inout"  "F - test-allocate-with-no-inout: error message")
14463     # check that stop(1) was called
14464     (check-ints-equal *(edx+4) 2 "F - test-allocate-with-no-inout: exit status")
14465     # don't restore from ebp
14466     81 0/subop/add %esp 8/imm32
14467     # . epilogue
14468     5d/pop-to-ebp
14469     c3/return
14470 
14471 test-allocate-with-too-many-inouts:
14472     # . prologue
14473     55/push-ebp
14474     89/<- %ebp 4/r32/esp
14475     # setup
14476     (clear-stream _test-input-stream)
14477     (clear-stream $_test-input-buffered-file->buffer)
14478     (clear-stream _test-output-stream)
14479     (clear-stream $_test-output-buffered-file->buffer)
14480     (clear-stream _test-error-stream)
14481     (clear-stream $_test-error-buffered-file->buffer)
14482     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14483     68/push 0/imm32
14484     68/push 0/imm32
14485     89/<- %edx 4/r32/esp
14486     (tailor-exit-descriptor %edx 0x10)
14487     #
14488     (write _test-input-stream "fn foo {\n")
14489     (write _test-input-stream "  var x: (addr handle int)\n")
14490     (write _test-input-stream "  allocate x, 0\n")
14491     (write _test-input-stream "}\n")
14492     # convert
14493     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14494     # registers except esp clobbered at this point
14495     # restore ed
14496     89/<- %edx 4/r32/esp
14497     (flush _test-output-buffered-file)
14498     (flush _test-error-buffered-file)
14499 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14505     # check output
14506     (check-stream-equal _test-output-stream  ""  "F - test-allocate-with-too-many-inouts: output should be empty")
14507     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'allocate' must have a single inout"  "F - test-allocate-with-too-many-inouts: error message")
14508     # check that stop(1) was called
14509     (check-ints-equal *(edx+4) 2 "F - test-allocate-with-too-many-inouts: exit status")
14510     # don't restore from ebp
14511     81 0/subop/add %esp 8/imm32
14512     # . epilogue
14513     5d/pop-to-ebp
14514     c3/return
14515 
14516 test-allocate-with-output:
14517     # . prologue
14518     55/push-ebp
14519     89/<- %ebp 4/r32/esp
14520     # setup
14521     (clear-stream _test-input-stream)
14522     (clear-stream $_test-input-buffered-file->buffer)
14523     (clear-stream _test-output-stream)
14524     (clear-stream $_test-output-buffered-file->buffer)
14525     (clear-stream _test-error-stream)
14526     (clear-stream $_test-error-buffered-file->buffer)
14527     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14528     68/push 0/imm32
14529     68/push 0/imm32
14530     89/<- %edx 4/r32/esp
14531     (tailor-exit-descriptor %edx 0x10)
14532     #
14533     (write _test-input-stream "fn foo {\n")
14534     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
14535     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
14536     (write _test-input-stream "  x <- allocate y\n")
14537     (write _test-input-stream "}\n")
14538     # convert
14539     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14540     # registers except esp clobbered at this point
14541     # restore ed
14542     89/<- %edx 4/r32/esp
14543     (flush _test-output-buffered-file)
14544     (flush _test-error-buffered-file)
14545 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14551     # check output
14552     (check-stream-equal _test-output-stream  ""  "F - test-allocate-with-output: output should be empty")
14553     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'allocate' must not have any outputs"  "F - test-allocate-with-output: error message")
14554     # check that stop(1) was called
14555     (check-ints-equal *(edx+4) 2 "F - test-allocate-with-output: exit status")
14556     # don't restore from ebp
14557     81 0/subop/add %esp 8/imm32
14558     # . epilogue
14559     5d/pop-to-ebp
14560     c3/return
14561 
14562 test-allocate-non-addr:
14563     # . prologue
14564     55/push-ebp
14565     89/<- %ebp 4/r32/esp
14566     # setup
14567     (clear-stream _test-input-stream)
14568     (clear-stream $_test-input-buffered-file->buffer)
14569     (clear-stream _test-output-stream)
14570     (clear-stream $_test-output-buffered-file->buffer)
14571     (clear-stream _test-error-stream)
14572     (clear-stream $_test-error-buffered-file->buffer)
14573     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14574     68/push 0/imm32
14575     68/push 0/imm32
14576     89/<- %edx 4/r32/esp
14577     (tailor-exit-descriptor %edx 0x10)
14578     #
14579     (write _test-input-stream "fn foo {\n")
14580     (write _test-input-stream "  var y: (handle int)\n")
14581     (write _test-input-stream "  allocate y\n")
14582     (write _test-input-stream "}\n")
14583     # convert
14584     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14585     # registers except esp clobbered at this point
14586     # restore ed
14587     89/<- %edx 4/r32/esp
14588     (flush _test-output-buffered-file)
14589     (flush _test-error-buffered-file)
14590 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14596     # check output
14597     (check-stream-equal _test-output-stream  ""  "F - test-allocate-non-addr: output must be empty")
14598     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt allocate: inout 'y' must have type (addr handle ...)"  "F - test-allocate-non-addr: error message")
14599     # check that stop(1) was called
14600     (check-ints-equal *(edx+4) 2 "F - test-allocate-non-addr: exit status")
14601     # don't restore from ebp
14602     81 0/subop/add %esp 8/imm32
14603     # . epilogue
14604     5d/pop-to-ebp
14605     c3/return
14606 
14607 test-allocate-non-addr-handle:
14608     # . prologue
14609     55/push-ebp
14610     89/<- %ebp 4/r32/esp
14611     # setup
14612     (clear-stream _test-input-stream)
14613     (clear-stream $_test-input-buffered-file->buffer)
14614     (clear-stream _test-output-stream)
14615     (clear-stream $_test-output-buffered-file->buffer)
14616     (clear-stream _test-error-stream)
14617     (clear-stream $_test-error-buffered-file->buffer)
14618     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14619     68/push 0/imm32
14620     68/push 0/imm32
14621     89/<- %edx 4/r32/esp
14622     (tailor-exit-descriptor %edx 0x10)
14623     #
14624     (write _test-input-stream "fn foo {\n")
14625     (write _test-input-stream "  var y/ecx: (addr int) <- copy 0\n")
14626     (write _test-input-stream "  allocate y\n")
14627     (write _test-input-stream "}\n")
14628     # convert
14629     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14630     # registers except esp clobbered at this point
14631     # restore ed
14632     89/<- %edx 4/r32/esp
14633     (flush _test-output-buffered-file)
14634     (flush _test-error-buffered-file)
14635 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14641     # check output
14642     (check-stream-equal _test-output-stream  ""  "F - test-allocate-non-addr-handle: output should be empty")
14643     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt allocate: inout 'y' must have type (addr handle ...)"  "F - test-allocate-non-addr-handle: error message")
14644     # check that stop(1) was called
14645     (check-ints-equal *(edx+4) 2 "F - test-allocate-non-addr-handle: exit status")
14646     # don't restore from ebp
14647     81 0/subop/add %esp 8/imm32
14648     # . epilogue
14649     5d/pop-to-ebp
14650     c3/return
14651 
14652 test-allocate-deref-address:
14653     # . prologue
14654     55/push-ebp
14655     89/<- %ebp 4/r32/esp
14656     # setup
14657     (clear-stream _test-input-stream)
14658     (clear-stream $_test-input-buffered-file->buffer)
14659     (clear-stream _test-output-stream)
14660     (clear-stream $_test-output-buffered-file->buffer)
14661     #
14662     (write _test-input-stream "fn foo {\n")
14663     (write _test-input-stream "  var y/ecx: (addr addr handle int) <- copy 0\n")
14664     (write _test-input-stream "  allocate *y\n")
14665     (write _test-input-stream "}\n")
14666     # convert
14667     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
14668     (flush _test-output-buffered-file)
14669     # no errors
14670     # . epilogue
14671     5d/pop-to-ebp
14672     c3/return
14673 
14674 test-populate-with-no-inout:
14675     # . prologue
14676     55/push-ebp
14677     89/<- %ebp 4/r32/esp
14678     # setup
14679     (clear-stream _test-input-stream)
14680     (clear-stream $_test-input-buffered-file->buffer)
14681     (clear-stream _test-output-stream)
14682     (clear-stream $_test-output-buffered-file->buffer)
14683     (clear-stream _test-error-stream)
14684     (clear-stream $_test-error-buffered-file->buffer)
14685     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14686     68/push 0/imm32
14687     68/push 0/imm32
14688     89/<- %edx 4/r32/esp
14689     (tailor-exit-descriptor %edx 0x10)
14690     #
14691     (write _test-input-stream "fn foo {\n")
14692     (write _test-input-stream "  populate\n")
14693     (write _test-input-stream "}\n")
14694     # convert
14695     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14696     # registers except esp clobbered at this point
14697     # restore ed
14698     89/<- %edx 4/r32/esp
14699     (flush _test-output-buffered-file)
14700     (flush _test-error-buffered-file)
14701 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14707     # check output
14708     (check-stream-equal _test-output-stream  ""  "F - test-populate-with-no-inout: output should be empty")
14709     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'populate' must have two inouts"  "F - test-populate-with-no-inout: error message")
14710     # check that stop(1) was called
14711     (check-ints-equal *(edx+4) 2 "F - test-populate-with-no-inout: exit status")
14712     # don't restore from ebp
14713     81 0/subop/add %esp 8/imm32
14714     # . epilogue
14715     5d/pop-to-ebp
14716     c3/return
14717 
14718 test-populate-with-too-many-inouts:
14719     # . prologue
14720     55/push-ebp
14721     89/<- %ebp 4/r32/esp
14722     # setup
14723     (clear-stream _test-input-stream)
14724     (clear-stream $_test-input-buffered-file->buffer)
14725     (clear-stream _test-output-stream)
14726     (clear-stream $_test-output-buffered-file->buffer)
14727     (clear-stream _test-error-stream)
14728     (clear-stream $_test-error-buffered-file->buffer)
14729     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14730     68/push 0/imm32
14731     68/push 0/imm32
14732     89/<- %edx 4/r32/esp
14733     (tailor-exit-descriptor %edx 0x10)
14734     #
14735     (write _test-input-stream "fn foo {\n")
14736     (write _test-input-stream "  var x: (addr handle int)\n")
14737     (write _test-input-stream "  populate x, 3, 0\n")
14738     (write _test-input-stream "}\n")
14739     # convert
14740     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14741     # registers except esp clobbered at this point
14742     # restore ed
14743     89/<- %edx 4/r32/esp
14744     (flush _test-output-buffered-file)
14745     (flush _test-error-buffered-file)
14746 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14752     # check output
14753     (check-stream-equal _test-output-stream  ""  "F - test-populate-with-too-many-inouts: output should be empty")
14754     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'populate' must have two inouts"  "F - test-populate-with-too-many-inouts: error message")
14755     # check that stop(1) was called
14756     (check-ints-equal *(edx+4) 2 "F - test-populate-with-too-many-inouts: exit status")
14757     # don't restore from ebp
14758     81 0/subop/add %esp 8/imm32
14759     # . epilogue
14760     5d/pop-to-ebp
14761     c3/return
14762 
14763 test-populate-with-output:
14764     # . prologue
14765     55/push-ebp
14766     89/<- %ebp 4/r32/esp
14767     # setup
14768     (clear-stream _test-input-stream)
14769     (clear-stream $_test-input-buffered-file->buffer)
14770     (clear-stream _test-output-stream)
14771     (clear-stream $_test-output-buffered-file->buffer)
14772     (clear-stream _test-error-stream)
14773     (clear-stream $_test-error-buffered-file->buffer)
14774     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14775     68/push 0/imm32
14776     68/push 0/imm32
14777     89/<- %edx 4/r32/esp
14778     (tailor-exit-descriptor %edx 0x10)
14779     #
14780     (write _test-input-stream "fn foo {\n")
14781     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
14782     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
14783     (write _test-input-stream "  x <- populate y\n")
14784     (write _test-input-stream "}\n")
14785     # convert
14786     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14787     # registers except esp clobbered at this point
14788     # restore ed
14789     89/<- %edx 4/r32/esp
14790     (flush _test-output-buffered-file)
14791     (flush _test-error-buffered-file)
14792 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14798     # check output
14799     (check-stream-equal _test-output-stream  ""  "F - test-populate-with-output: output should be empty")
14800     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'populate' must not have any outputs"  "F - test-populate-with-output: error message")
14801     # check that stop(1) was called
14802     (check-ints-equal *(edx+4) 2 "F - test-populate-with-output: exit status")
14803     # don't restore from ebp
14804     81 0/subop/add %esp 8/imm32
14805     # . epilogue
14806     5d/pop-to-ebp
14807     c3/return
14808 
14809 test-populate-non-addr:
14810     # . prologue
14811     55/push-ebp
14812     89/<- %ebp 4/r32/esp
14813     # setup
14814     (clear-stream _test-input-stream)
14815     (clear-stream $_test-input-buffered-file->buffer)
14816     (clear-stream _test-output-stream)
14817     (clear-stream $_test-output-buffered-file->buffer)
14818     (clear-stream _test-error-stream)
14819     (clear-stream $_test-error-buffered-file->buffer)
14820     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14821     68/push 0/imm32
14822     68/push 0/imm32
14823     89/<- %edx 4/r32/esp
14824     (tailor-exit-descriptor %edx 0x10)
14825     #
14826     (write _test-input-stream "fn foo {\n")
14827     (write _test-input-stream "  var y: (handle int)\n")
14828     (write _test-input-stream "  populate y, 3\n")
14829     (write _test-input-stream "}\n")
14830     # convert
14831     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14832     # registers except esp clobbered at this point
14833     # restore ed
14834     89/<- %edx 4/r32/esp
14835     (flush _test-output-buffered-file)
14836     (flush _test-error-buffered-file)
14837 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14843     # check output
14844     (check-stream-equal _test-output-stream  ""  "F - test-populate-non-addr: output must be empty")
14845     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt populate: first inout 'y' must have type (addr handle array ...)"  "F - test-populate-non-addr: error message")
14846     # check that stop(1) was called
14847     (check-ints-equal *(edx+4) 2 "F - test-populate-non-addr: exit status")
14848     # don't restore from ebp
14849     81 0/subop/add %esp 8/imm32
14850     # . epilogue
14851     5d/pop-to-ebp
14852     c3/return
14853 
14854 test-populate-non-addr-handle:
14855     # . prologue
14856     55/push-ebp
14857     89/<- %ebp 4/r32/esp
14858     # setup
14859     (clear-stream _test-input-stream)
14860     (clear-stream $_test-input-buffered-file->buffer)
14861     (clear-stream _test-output-stream)
14862     (clear-stream $_test-output-buffered-file->buffer)
14863     (clear-stream _test-error-stream)
14864     (clear-stream $_test-error-buffered-file->buffer)
14865     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14866     68/push 0/imm32
14867     68/push 0/imm32
14868     89/<- %edx 4/r32/esp
14869     (tailor-exit-descriptor %edx 0x10)
14870     #
14871     (write _test-input-stream "fn foo {\n")
14872     (write _test-input-stream "  var y/ecx: (addr int) <- copy 0\n")
14873     (write _test-input-stream "  populate y, 3\n")
14874     (write _test-input-stream "}\n")
14875     # convert
14876     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14877     # registers except esp clobbered at this point
14878     # restore ed
14879     89/<- %edx 4/r32/esp
14880     (flush _test-output-buffered-file)
14881     (flush _test-error-buffered-file)
14882 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14888     # check output
14889     (check-stream-equal _test-output-stream  ""  "F - test-populate-non-addr-handle: output should be empty")
14890     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt populate: first inout 'y' must have type (addr handle array ...)"  "F - test-populate-non-addr-handle: error message")
14891     # check that stop(1) was called
14892     (check-ints-equal *(edx+4) 2 "F - test-populate-non-addr-handle: exit status")
14893     # don't restore from ebp
14894     81 0/subop/add %esp 8/imm32
14895     # . epilogue
14896     5d/pop-to-ebp
14897     c3/return
14898 
14899 test-populate-non-addr-handle-array:
14900     # . prologue
14901     55/push-ebp
14902     89/<- %ebp 4/r32/esp
14903     # setup
14904     (clear-stream _test-input-stream)
14905     (clear-stream $_test-input-buffered-file->buffer)
14906     (clear-stream _test-output-stream)
14907     (clear-stream $_test-output-buffered-file->buffer)
14908     (clear-stream _test-error-stream)
14909     (clear-stream $_test-error-buffered-file->buffer)
14910     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14911     68/push 0/imm32
14912     68/push 0/imm32
14913     89/<- %edx 4/r32/esp
14914     (tailor-exit-descriptor %edx 0x10)
14915     #
14916     (write _test-input-stream "fn foo {\n")
14917     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
14918     (write _test-input-stream "  populate y, 3\n")
14919     (write _test-input-stream "}\n")
14920     # convert
14921     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14922     # registers except esp clobbered at this point
14923     # restore ed
14924     89/<- %edx 4/r32/esp
14925     (flush _test-output-buffered-file)
14926     (flush _test-error-buffered-file)
14927 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14933     # check output
14934     (check-stream-equal _test-output-stream  ""  "F - test-populate-non-addr-handle-array: output should be empty")
14935     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt populate: first inout 'y' must have type (addr handle array ...)"  "F - test-populate-non-addr-handle-array: error message")
14936     # check that stop(1) was called
14937     (check-ints-equal *(edx+4) 2 "F - test-populate-non-addr-handle-array: exit status")
14938     # don't restore from ebp
14939     81 0/subop/add %esp 8/imm32
14940     # . epilogue
14941     5d/pop-to-ebp
14942     c3/return
14943 
14944 test-populate-deref-address:
14945     # . prologue
14946     55/push-ebp
14947     89/<- %ebp 4/r32/esp
14948     # setup
14949     (clear-stream _test-input-stream)
14950     (clear-stream $_test-input-buffered-file->buffer)
14951     (clear-stream _test-output-stream)
14952     (clear-stream $_test-output-buffered-file->buffer)
14953     #
14954     (write _test-input-stream "fn foo {\n")
14955     (write _test-input-stream "  var y/ecx: (addr addr handle array int) <- copy 0\n")
14956     (write _test-input-stream "  populate *y, 3\n")
14957     (write _test-input-stream "}\n")
14958     # convert
14959     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
14960     (flush _test-output-buffered-file)
14961     # no errors
14962     # . epilogue
14963     5d/pop-to-ebp
14964     c3/return
14965 
14966 test-populate-stream-with-no-inout:
14967     # . prologue
14968     55/push-ebp
14969     89/<- %ebp 4/r32/esp
14970     # setup
14971     (clear-stream _test-input-stream)
14972     (clear-stream $_test-input-buffered-file->buffer)
14973     (clear-stream _test-output-stream)
14974     (clear-stream $_test-output-buffered-file->buffer)
14975     (clear-stream _test-error-stream)
14976     (clear-stream $_test-error-buffered-file->buffer)
14977     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14978     68/push 0/imm32
14979     68/push 0/imm32
14980     89/<- %edx 4/r32/esp
14981     (tailor-exit-descriptor %edx 0x10)
14982     #
14983     (write _test-input-stream "fn foo {\n")
14984     (write _test-input-stream "  populate-stream\n")
14985     (write _test-input-stream "}\n")
14986     # convert
14987     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14988     # registers except esp clobbered at this point
14989     # restore ed
14990     89/<- %edx 4/r32/esp
14991     (flush _test-output-buffered-file)
14992     (flush _test-error-buffered-file)
14993 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14999     # check output
15000     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-with-no-inout: output should be empty")
15001     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'populate-stream' must have two inouts"  "F - test-populate-stream-with-no-inout: error message")
15002     # check that stop(1) was called
15003     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-with-no-inout: exit status")
15004     # don't restore from ebp
15005     81 0/subop/add %esp 8/imm32
15006     # . epilogue
15007     5d/pop-to-ebp
15008     c3/return
15009 
15010 test-populate-stream-with-too-many-inouts:
15011     # . prologue
15012     55/push-ebp
15013     89/<- %ebp 4/r32/esp
15014     # setup
15015     (clear-stream _test-input-stream)
15016     (clear-stream $_test-input-buffered-file->buffer)
15017     (clear-stream _test-output-stream)
15018     (clear-stream $_test-output-buffered-file->buffer)
15019     (clear-stream _test-error-stream)
15020     (clear-stream $_test-error-buffered-file->buffer)
15021     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15022     68/push 0/imm32
15023     68/push 0/imm32
15024     89/<- %edx 4/r32/esp
15025     (tailor-exit-descriptor %edx 0x10)
15026     #
15027     (write _test-input-stream "fn foo {\n")
15028     (write _test-input-stream "  var x: (addr handle int)\n")
15029     (write _test-input-stream "  populate-stream x, 3, 0\n")
15030     (write _test-input-stream "}\n")
15031     # convert
15032     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15033     # registers except esp clobbered at this point
15034     # restore ed
15035     89/<- %edx 4/r32/esp
15036     (flush _test-output-buffered-file)
15037     (flush _test-error-buffered-file)
15038 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15044     # check output
15045     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-with-too-many-inouts: output should be empty")
15046     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'populate-stream' must have two inouts"  "F - test-populate-stream-with-too-many-inouts: error message")
15047     # check that stop(1) was called
15048     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-with-too-many-inouts: exit status")
15049     # don't restore from ebp
15050     81 0/subop/add %esp 8/imm32
15051     # . epilogue
15052     5d/pop-to-ebp
15053     c3/return
15054 
15055 test-populate-stream-with-output:
15056     # . prologue
15057     55/push-ebp
15058     89/<- %ebp 4/r32/esp
15059     # setup
15060     (clear-stream _test-input-stream)
15061     (clear-stream $_test-input-buffered-file->buffer)
15062     (clear-stream _test-output-stream)
15063     (clear-stream $_test-output-buffered-file->buffer)
15064     (clear-stream _test-error-stream)
15065     (clear-stream $_test-error-buffered-file->buffer)
15066     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15067     68/push 0/imm32
15068     68/push 0/imm32
15069     89/<- %edx 4/r32/esp
15070     (tailor-exit-descriptor %edx 0x10)
15071     #
15072     (write _test-input-stream "fn foo {\n")
15073     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
15074     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
15075     (write _test-input-stream "  x <- populate-stream y\n")
15076     (write _test-input-stream "}\n")
15077     # convert
15078     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15079     # registers except esp clobbered at this point
15080     # restore ed
15081     89/<- %edx 4/r32/esp
15082     (flush _test-output-buffered-file)
15083     (flush _test-error-buffered-file)
15084 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15090     # check output
15091     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-with-output: output should be empty")
15092     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'populate-stream' must not have any outputs"  "F - test-populate-stream-with-output: error message")
15093     # check that stop(1) was called
15094     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-with-output: exit status")
15095     # don't restore from ebp
15096     81 0/subop/add %esp 8/imm32
15097     # . epilogue
15098     5d/pop-to-ebp
15099     c3/return
15100 
15101 test-populate-stream-non-addr:
15102     # . prologue
15103     55/push-ebp
15104     89/<- %ebp 4/r32/esp
15105     # setup
15106     (clear-stream _test-input-stream)
15107     (clear-stream $_test-input-buffered-file->buffer)
15108     (clear-stream _test-output-stream)
15109     (clear-stream $_test-output-buffered-file->buffer)
15110     (clear-stream _test-error-stream)
15111     (clear-stream $_test-error-buffered-file->buffer)
15112     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15113     68/push 0/imm32
15114     68/push 0/imm32
15115     89/<- %edx 4/r32/esp
15116     (tailor-exit-descriptor %edx 0x10)
15117     #
15118     (write _test-input-stream "fn foo {\n")
15119     (write _test-input-stream "  var y: (handle int)\n")
15120     (write _test-input-stream "  populate-stream y, 3\n")
15121     (write _test-input-stream "}\n")
15122     # convert
15123     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15124     # registers except esp clobbered at this point
15125     # restore ed
15126     89/<- %edx 4/r32/esp
15127     (flush _test-output-buffered-file)
15128     (flush _test-error-buffered-file)
15129 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15135     # check output
15136     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-non-addr: output must be empty")
15137     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt populate-stream: first inout 'y' must have type (addr handle stream ...)"  "F - test-populate-stream-non-addr: error message")
15138     # check that stop(1) was called
15139     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-non-addr: exit status")
15140     # don't restore from ebp
15141     81 0/subop/add %esp 8/imm32
15142     # . epilogue
15143     5d/pop-to-ebp
15144     c3/return
15145 
15146 test-populate-stream-non-addr-handle:
15147     # . prologue
15148     55/push-ebp
15149     89/<- %ebp 4/r32/esp
15150     # setup
15151     (clear-stream _test-input-stream)
15152     (clear-stream $_test-input-buffered-file->buffer)
15153     (clear-stream _test-output-stream)
15154     (clear-stream $_test-output-buffered-file->buffer)
15155     (clear-stream _test-error-stream)
15156     (clear-stream $_test-error-buffered-file->buffer)
15157     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15158     68/push 0/imm32
15159     68/push 0/imm32
15160     89/<- %edx 4/r32/esp
15161     (tailor-exit-descriptor %edx 0x10)
15162     #
15163     (write _test-input-stream "fn foo {\n")
15164     (write _test-input-stream "  var y/ecx: (addr int) <- copy 0\n")
15165     (write _test-input-stream "  populate-stream y, 3\n")
15166     (write _test-input-stream "}\n")
15167     # convert
15168     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15169     # registers except esp clobbered at this point
15170     # restore ed
15171     89/<- %edx 4/r32/esp
15172     (flush _test-output-buffered-file)
15173     (flush _test-error-buffered-file)
15174 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15180     # check output
15181     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-non-addr-handle: output should be empty")
15182     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt populate-stream: first inout 'y' must have type (addr handle stream ...)"  "F - test-populate-stream-non-addr-handle: error message")
15183     # check that stop(1) was called
15184     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-non-addr-handle: exit status")
15185     # don't restore from ebp
15186     81 0/subop/add %esp 8/imm32
15187     # . epilogue
15188     5d/pop-to-ebp
15189     c3/return
15190 
15191 test-populate-stream-non-addr-handle-stream:
15192     # . prologue
15193     55/push-ebp
15194     89/<- %ebp 4/r32/esp
15195     # setup
15196     (clear-stream _test-input-stream)
15197     (clear-stream $_test-input-buffered-file->buffer)
15198     (clear-stream _test-output-stream)
15199     (clear-stream $_test-output-buffered-file->buffer)
15200     (clear-stream _test-error-stream)
15201     (clear-stream $_test-error-buffered-file->buffer)
15202     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15203     68/push 0/imm32
15204     68/push 0/imm32
15205     89/<- %edx 4/r32/esp
15206     (tailor-exit-descriptor %edx 0x10)
15207     #
15208     (write _test-input-stream "fn foo {\n")
15209     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
15210     (write _test-input-stream "  populate-stream y, 3\n")
15211     (write _test-input-stream "}\n")
15212     # convert
15213     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15214     # registers except esp clobbered at this point
15215     # restore ed
15216     89/<- %edx 4/r32/esp
15217     (flush _test-output-buffered-file)
15218     (flush _test-error-buffered-file)
15219 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15225     # check output
15226     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-non-addr-handle-stream: output should be empty")
15227     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt populate-stream: first inout 'y' must have type (addr handle stream ...)"  "F - test-populate-stream-non-addr-handle-stream: error message")
15228     # check that stop(1) was called
15229     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-non-addr-handle-stream: exit status")
15230     # don't restore from ebp
15231     81 0/subop/add %esp 8/imm32
15232     # . epilogue
15233     5d/pop-to-ebp
15234     c3/return
15235 
15236 test-populate-stream-deref-address:
15237     # . prologue
15238     55/push-ebp
15239     89/<- %ebp 4/r32/esp
15240     # setup
15241     (clear-stream _test-input-stream)
15242     (clear-stream $_test-input-buffered-file->buffer)
15243     (clear-stream _test-output-stream)
15244     (clear-stream $_test-output-buffered-file->buffer)
15245     #
15246     (write _test-input-stream "fn foo {\n")
15247     (write _test-input-stream "  var y/ecx: (addr addr handle stream int) <- copy 0\n")
15248     (write _test-input-stream "  populate-stream *y, 3\n")
15249     (write _test-input-stream "}\n")
15250     # convert
15251     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
15252     (flush _test-output-buffered-file)
15253     # no errors
15254     # . epilogue
15255     5d/pop-to-ebp
15256     c3/return
15257 
15258 test-convert-with-no-inout:
15259     # . prologue
15260     55/push-ebp
15261     89/<- %ebp 4/r32/esp
15262     # setup
15263     (clear-stream _test-input-stream)
15264     (clear-stream $_test-input-buffered-file->buffer)
15265     (clear-stream _test-output-stream)
15266     (clear-stream $_test-output-buffered-file->buffer)
15267     (clear-stream _test-error-stream)
15268     (clear-stream $_test-error-buffered-file->buffer)
15269     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15270     68/push 0/imm32
15271     68/push 0/imm32
15272     89/<- %edx 4/r32/esp
15273     (tailor-exit-descriptor %edx 0x10)
15274     #
15275     (write _test-input-stream "fn foo {\n")
15276     (write _test-input-stream "  var x/eax: int <- convert\n")
15277     (write _test-input-stream "}\n")
15278     # convert
15279     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15280     # registers except esp clobbered at this point
15281     # restore ed
15282     89/<- %edx 4/r32/esp
15283     (flush _test-output-buffered-file)
15284     (flush _test-error-buffered-file)
15285 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15291     # check output
15292     (check-stream-equal _test-output-stream  ""  "F - test-convert-with-no-inout: output should be empty")
15293     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'convert' expects an inout"  "F - test-convert-with-no-inout: error message")
15294     # check that stop(1) was called
15295     (check-ints-equal *(edx+4) 2 "F - test-convert-with-no-inout: exit status")
15296     # don't restore from ebp
15297     81 0/subop/add %esp 8/imm32
15298     # . epilogue
15299     5d/pop-to-ebp
15300     c3/return
15301 
15302 test-convert-with-multiple-inouts:
15303     # . prologue
15304     55/push-ebp
15305     89/<- %ebp 4/r32/esp
15306     # setup
15307     (clear-stream _test-input-stream)
15308     (clear-stream $_test-input-buffered-file->buffer)
15309     (clear-stream _test-output-stream)
15310     (clear-stream $_test-output-buffered-file->buffer)
15311     (clear-stream _test-error-stream)
15312     (clear-stream $_test-error-buffered-file->buffer)
15313     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15314     68/push 0/imm32
15315     68/push 0/imm32
15316     89/<- %edx 4/r32/esp
15317     (tailor-exit-descriptor %edx 0x10)
15318     #
15319     (write _test-input-stream "fn foo {\n")
15320     (write _test-input-stream "  var x/eax: int <- convert 0, 0\n")
15321     (write _test-input-stream "}\n")
15322     # convert
15323     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15324     # registers except esp clobbered at this point
15325     # restore ed
15326     89/<- %edx 4/r32/esp
15327     (flush _test-output-buffered-file)
15328     (flush _test-error-buffered-file)
15329 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15335     # check output
15336     (check-stream-equal _test-output-stream  ""  "F - test-convert-with-multiple-inouts: output should be empty")
15337     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'convert' must have just one inout"  "F - test-convert-with-multiple-inouts: error message")
15338     # check that stop(1) was called
15339     (check-ints-equal *(edx+4) 2 "F - test-convert-with-multiple-inouts: exit status")
15340     # don't restore from ebp
15341     81 0/subop/add %esp 8/imm32
15342     # . epilogue
15343     5d/pop-to-ebp
15344     c3/return
15345 
15346 test-convert-with-no-output:
15347     # . prologue
15348     55/push-ebp
15349     89/<- %ebp 4/r32/esp
15350     # setup
15351     (clear-stream _test-input-stream)
15352     (clear-stream $_test-input-buffered-file->buffer)
15353     (clear-stream _test-output-stream)
15354     (clear-stream $_test-output-buffered-file->buffer)
15355     (clear-stream _test-error-stream)
15356     (clear-stream $_test-error-buffered-file->buffer)
15357     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15358     68/push 0/imm32
15359     68/push 0/imm32
15360     89/<- %edx 4/r32/esp
15361     (tailor-exit-descriptor %edx 0x10)
15362     #
15363     (write _test-input-stream "fn foo {\n")
15364     (write _test-input-stream "  convert 0\n")
15365     (write _test-input-stream "}\n")
15366     # convert
15367     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15368     # registers except esp clobbered at this point
15369     # restore ed
15370     89/<- %edx 4/r32/esp
15371     (flush _test-output-buffered-file)
15372     (flush _test-error-buffered-file)
15373 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15379     # check output
15380     (check-stream-equal _test-output-stream  ""  "F - test-convert-with-no-output: output should be empty")
15381     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'convert' expects an output"  "F - test-convert-with-no-output: error message")
15382     # check that stop(1) was called
15383     (check-ints-equal *(edx+4) 2 "F - test-convert-with-no-output: exit status")
15384     # don't restore from ebp
15385     81 0/subop/add %esp 8/imm32
15386     # . epilogue
15387     5d/pop-to-ebp
15388     c3/return
15389 
15390 test-convert-with-multiple-outputs:
15391     # . prologue
15392     55/push-ebp
15393     89/<- %ebp 4/r32/esp
15394     # setup
15395     (clear-stream _test-input-stream)
15396     (clear-stream $_test-input-buffered-file->buffer)
15397     (clear-stream _test-output-stream)
15398     (clear-stream $_test-output-buffered-file->buffer)
15399     (clear-stream _test-error-stream)
15400     (clear-stream $_test-error-buffered-file->buffer)
15401     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15402     68/push 0/imm32
15403     68/push 0/imm32
15404     89/<- %edx 4/r32/esp
15405     (tailor-exit-descriptor %edx 0x10)
15406     #
15407     (write _test-input-stream "fn foo {\n")
15408     (write _test-input-stream "  var x/eax: int <- copy 0\n")
15409     (write _test-input-stream "  var y/ecx: int <- copy 0\n")
15410     (write _test-input-stream "  x, y <- convert 0\n")
15411     (write _test-input-stream "}\n")
15412     # convert
15413     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15414     # registers except esp clobbered at this point
15415     # restore ed
15416     89/<- %edx 4/r32/esp
15417     (flush _test-output-buffered-file)
15418     (flush _test-error-buffered-file)
15419 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15425     # check output
15426     (check-stream-equal _test-output-stream  ""  "F - test-convert-with-multiple-outputs: output should be empty")
15427     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'convert' must have just one output"  "F - test-convert-with-multiple-outputs: error message")
15428     # check that stop(1) was called
15429     (check-ints-equal *(edx+4) 2 "F - test-convert-with-multiple-outputs: exit status")
15430     # don't restore from ebp
15431     81 0/subop/add %esp 8/imm32
15432     # . epilogue
15433     5d/pop-to-ebp
15434     c3/return
15435 
15436 test-convert-deref-address:
15437     # . prologue
15438     55/push-ebp
15439     89/<- %ebp 4/r32/esp
15440     # setup
15441     (clear-stream _test-input-stream)
15442     (clear-stream $_test-input-buffered-file->buffer)
15443     (clear-stream _test-output-stream)
15444     (clear-stream $_test-output-buffered-file->buffer)
15445     #
15446     (write _test-input-stream "fn foo {\n")
15447     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
15448     (write _test-input-stream "  var y/xmm4: float <- convert *x\n")
15449     (write _test-input-stream "}\n")
15450     # convert
15451     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
15452     (flush _test-output-buffered-file)
15453     # no errors
15454     # . epilogue
15455     5d/pop-to-ebp
15456     c3/return
15457 
15458 test-convert-to-non-register:
15459     # . prologue
15460     55/push-ebp
15461     89/<- %ebp 4/r32/esp
15462     # setup
15463     (clear-stream _test-input-stream)
15464     (clear-stream $_test-input-buffered-file->buffer)
15465     (clear-stream _test-output-stream)
15466     (clear-stream $_test-output-buffered-file->buffer)
15467     (clear-stream _test-error-stream)
15468     (clear-stream $_test-error-buffered-file->buffer)
15469     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15470     68/push 0/imm32
15471     68/push 0/imm32
15472     89/<- %edx 4/r32/esp
15473     (tailor-exit-descriptor %edx 0x10)
15474     #
15475     (write _test-input-stream "fn foo {\n")
15476     (write _test-input-stream "  var x: float\n")
15477     (write _test-input-stream "  var y: int\n")
15478     (write _test-input-stream "  x <- convert y\n")
15479     (write _test-input-stream "}\n")
15480     # convert
15481     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15482     # registers except esp clobbered at this point
15483     # restore ed
15484     89/<- %edx 4/r32/esp
15485     (flush _test-output-buffered-file)
15486     (flush _test-error-buffered-file)
15487 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15493     # check output
15494     (check-stream-equal _test-output-stream  ""  "F - test-convert-to-non-register: output should be empty")
15495     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt convert: output 'x' not in a register"  "F - test-convert-to-non-register: error message")
15496     # check that stop(1) was called
15497     (check-ints-equal *(edx+4) 2 "F - test-convert-to-non-register: exit status")
15498     # don't restore from ebp
15499     81 0/subop/add %esp 8/imm32
15500     # . epilogue
15501     5d/pop-to-ebp
15502     c3/return
15503 
15504 test-convert-invalid-inout-type:
15505     # . prologue
15506     55/push-ebp
15507     89/<- %ebp 4/r32/esp
15508     # setup
15509     (clear-stream _test-input-stream)
15510     (clear-stream $_test-input-buffered-file->buffer)
15511     (clear-stream _test-output-stream)
15512     (clear-stream $_test-output-buffered-file->buffer)
15513     (clear-stream _test-error-stream)
15514     (clear-stream $_test-error-buffered-file->buffer)
15515     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15516     68/push 0/imm32
15517     68/push 0/imm32
15518     89/<- %edx 4/r32/esp
15519     (tailor-exit-descriptor %edx 0x10)
15520     #
15521     (write _test-input-stream "fn foo {\n")
15522     (write _test-input-stream "  var x: boolean\n")
15523     (write _test-input-stream "  var y/xmm1: float <- convert x\n")
15524     (write _test-input-stream "}\n")
15525     # convert
15526     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15527     # registers except esp clobbered at this point
15528     # restore ed
15529     89/<- %edx 4/r32/esp
15530     (flush _test-output-buffered-file)
15531     (flush _test-error-buffered-file)
15532 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15538     # check output
15539     (check-stream-equal _test-output-stream  ""  "F - test-convert-invalid-inout-type: output should be empty")
15540     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt convert: inout 'x' must be an int or float"  "F - test-convert-invalid-inout-type: error message")
15541     # check that stop(1) was called
15542     (check-ints-equal *(edx+4) 2 "F - test-convert-invalid-inout-type: exit status")
15543     # don't restore from ebp
15544     81 0/subop/add %esp 8/imm32
15545     # . epilogue
15546     5d/pop-to-ebp
15547     c3/return
15548 
15549 test-convert-invalid-output-type:
15550     # . prologue
15551     55/push-ebp
15552     89/<- %ebp 4/r32/esp
15553     # setup
15554     (clear-stream _test-input-stream)
15555     (clear-stream $_test-input-buffered-file->buffer)
15556     (clear-stream _test-output-stream)
15557     (clear-stream $_test-output-buffered-file->buffer)
15558     (clear-stream _test-error-stream)
15559     (clear-stream $_test-error-buffered-file->buffer)
15560     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15561     68/push 0/imm32
15562     68/push 0/imm32
15563     89/<- %edx 4/r32/esp
15564     (tailor-exit-descriptor %edx 0x10)
15565     #
15566     (write _test-input-stream "fn foo {\n")
15567     (write _test-input-stream "  var x: float\n")
15568     (write _test-input-stream "  var y/eax: boolean <- convert x\n")
15569     (write _test-input-stream "}\n")
15570     # convert
15571     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15572     # registers except esp clobbered at this point
15573     # restore ed
15574     89/<- %edx 4/r32/esp
15575     (flush _test-output-buffered-file)
15576     (flush _test-error-buffered-file)
15577 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15583     # check output
15584     (check-stream-equal _test-output-stream  ""  "F - test-convert-invalid-output-type: output should be empty")
15585     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt convert: output 'y' must be an int or float"  "F - test-convert-invalid-output-type: error message")
15586     # check that stop(1) was called
15587     (check-ints-equal *(edx+4) 2 "F - test-convert-invalid-output-type: exit status")
15588     # don't restore from ebp
15589     81 0/subop/add %esp 8/imm32
15590     # . epilogue
15591     5d/pop-to-ebp
15592     c3/return
15593 
15594 test-convert-int-to-int:
15595     # . prologue
15596     55/push-ebp
15597     89/<- %ebp 4/r32/esp
15598     # setup
15599     (clear-stream _test-input-stream)
15600     (clear-stream $_test-input-buffered-file->buffer)
15601     (clear-stream _test-output-stream)
15602     (clear-stream $_test-output-buffered-file->buffer)
15603     (clear-stream _test-error-stream)
15604     (clear-stream $_test-error-buffered-file->buffer)
15605     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15606     68/push 0/imm32
15607     68/push 0/imm32
15608     89/<- %edx 4/r32/esp
15609     (tailor-exit-descriptor %edx 0x10)
15610     #
15611     (write _test-input-stream "fn foo {\n")
15612     (write _test-input-stream "  var x: int\n")
15613     (write _test-input-stream "  var y/eax: int <- convert x\n")
15614     (write _test-input-stream "}\n")
15615     # convert
15616     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15617     # registers except esp clobbered at this point
15618     # restore ed
15619     89/<- %edx 4/r32/esp
15620     (flush _test-output-buffered-file)
15621     (flush _test-error-buffered-file)
15622 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15628     # check output
15629     (check-stream-equal _test-output-stream  ""  "F - test-convert-int-to-int: output should be empty")
15630     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt convert: no need to convert int to int"  "F - test-convert-int-to-int: error message")
15631     # check that stop(1) was called
15632     (check-ints-equal *(edx+4) 2 "F - test-convert-int-to-int: exit status")
15633     # don't restore from ebp
15634     81 0/subop/add %esp 8/imm32
15635     # . epilogue
15636     5d/pop-to-ebp
15637     c3/return
15638 
15639 test-convert-float-to-float:
15640     # . prologue
15641     55/push-ebp
15642     89/<- %ebp 4/r32/esp
15643     # setup
15644     (clear-stream _test-input-stream)
15645     (clear-stream $_test-input-buffered-file->buffer)
15646     (clear-stream _test-output-stream)
15647     (clear-stream $_test-output-buffered-file->buffer)
15648     (clear-stream _test-error-stream)
15649     (clear-stream $_test-error-buffered-file->buffer)
15650     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15651     68/push 0/imm32
15652     68/push 0/imm32
15653     89/<- %edx 4/r32/esp
15654     (tailor-exit-descriptor %edx 0x10)
15655     #
15656     (write _test-input-stream "fn foo {\n")
15657     (write _test-input-stream "  var x: float\n")
15658     (write _test-input-stream "  var y/xmm6: float <- convert x\n")
15659     (write _test-input-stream "}\n")
15660     # convert
15661     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15662     # registers except esp clobbered at this point
15663     # restore ed
15664     89/<- %edx 4/r32/esp
15665     (flush _test-output-buffered-file)
15666     (flush _test-error-buffered-file)
15667 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15673     # check output
15674     (check-stream-equal _test-output-stream  ""  "F - test-convert-float-to-float: output should be empty")
15675     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt convert: no need to convert float to float"  "F - test-convert-float-to-float: error message")
15676     # check that stop(1) was called
15677     (check-ints-equal *(edx+4) 2 "F - test-convert-float-to-float: exit status")
15678     # don't restore from ebp
15679     81 0/subop/add %esp 8/imm32
15680     # . epilogue
15681     5d/pop-to-ebp
15682     c3/return
15683 
15684 #######################################################
15685 # Parsing
15686 #######################################################
15687 
15688 == data
15689 
15690 # Global state added to each var record when parsing a function
15691 Next-block-index:  # (addr int)
15692     1/imm32
15693 
15694 Curr-block-depth:  # (addr int)
15695     1/imm32
15696 
15697 == code
15698 
15699 parse-mu:  # in: (addr buffered-file), err: (addr buffered-file), ed: (addr exit-descriptor)
15700     # pseudocode
15701     #   var curr-function: (addr handle function) = Program->functions
15702     #   var curr-signature: (addr handle function) = Program->signatures
15703     #   var curr-type: (addr handle typeinfo) = Program->types
15704     #   var line: (stream byte 512)
15705     #   var word-slice: slice
15706     #   while true                                  # line loop
15707     #     clear-stream(line)
15708     #     read-line-buffered(in, line)
15709     #     if (line->write == 0) break               # end of file
15710     #     word-slice = next-mu-token(line)
15711     #     if slice-empty?(word-slice)               # end of line
15712     #       continue
15713     #     else if slice-starts-with?(word-slice, "#")  # comment
15714     #       continue                                # end of line
15715     #     else if slice-equal?(word-slice, "fn")
15716     #       var new-function: (handle function) = allocate(function)
15717     #       var vars: (stack live-var 256)
15718     #       populate-mu-function-header(line, new-function, vars)
15719     #       populate-mu-function-body(in, new-function, vars)
15720     #       assert(vars->top == 0)
15721     #       *curr-function = new-function
15722     #       curr-function = &new-function->next
15723     #     else if slice-equal?(word-slice, "sig")
15724     #       var new-function: (handle function) = allocate(function)
15725     #       populate-mu-function-signature(line, new-function)
15726     #       *curr-signature = new-function
15727     #       curr-signature = &new-function->next
15728     #     else if slice-equal?(word-slice, "type")
15729     #       word-slice = next-mu-token(line)
15730     #       type-id = pos-or-insert-slice(Type-id, word-slice)
15731     #       var new-type: (handle typeinfo) = find-or-create-typeinfo(type-id)
15732     #       assert(next-word(line) == "{")
15733     #       populate-mu-type(in, new-type)
15734     #     else
15735     #       abort()
15736     #
15737     # . prologue
15738     55/push-ebp
15739     89/<- %ebp 4/r32/esp
15740     # var curr-signature: (addr handle function) at *(ebp-4)
15741     68/push _Program-signatures/imm32
15742     # . save registers
15743     50/push-eax
15744     51/push-ecx
15745     52/push-edx
15746     53/push-ebx
15747     56/push-esi
15748     57/push-edi
15749     # var line/ecx: (stream byte 512)
15750     81 5/subop/subtract %esp 0x200/imm32
15751     68/push 0x200/imm32/size
15752     68/push 0/imm32/read
15753     68/push 0/imm32/write
15754     89/<- %ecx 4/r32/esp
15755     # var word-slice/edx: slice
15756     68/push 0/imm32/end
15757     68/push 0/imm32/start
15758     89/<- %edx 4/r32/esp
15759     # var curr-function/edi: (addr handle function)
15760     bf/copy-to-edi _Program-functions/imm32
15761     # var vars/ebx: (stack live-var 256)
15762     81 5/subop/subtract %esp 0xc00/imm32
15763     68/push 0xc00/imm32/size
15764     68/push 0/imm32/top
15765     89/<- %ebx 4/r32/esp
15766     {
15767 $parse-mu:line-loop:
15768       (clear-stream %ecx)
15769       (read-line-buffered *(ebp+8) %ecx)
15770       # if (line->write == 0) break
15771       81 7/subop/compare *ecx 0/imm32
15772       0f 84/jump-if-= break/disp32
15773 +--  6 lines: #?       # dump line ------------------------------------------------------------------------------------------------------------------------------------------------------
15779       (next-mu-token %ecx %edx)
15780       # if slice-empty?(word-slice) continue
15781       (slice-empty? %edx)  # => eax
15782       3d/compare-eax-and 0/imm32/false
15783       0f 85/jump-if-!= loop/disp32
15784       # if (*word-slice->start == "#") continue
15785       # . eax = *word-slice->start
15786       8b/-> *edx 0/r32/eax
15787       8a/copy-byte *eax 0/r32/AL
15788       81 4/subop/and %eax 0xff/imm32
15789       # . if (eax == '#') continue
15790       3d/compare-eax-and 0x23/imm32/hash
15791       0f 84/jump-if-= loop/disp32
15792       # if (slice-equal?(word-slice, "fn")) parse a function
15793       {
15794 $parse-mu:fn:
15795         (slice-equal? %edx "fn")  # => eax
15796         3d/compare-eax-and 0/imm32/false
15797         0f 84/jump-if-= break/disp32
15798         # var new-function/esi: (handle function)
15799         68/push 0/imm32
15800         68/push 0/imm32
15801         89/<- %esi 4/r32/esp
15802         # populate-mu-function(line, in, vars, new-function)
15803         (allocate Heap *Function-size %esi)
15804         # var new-function-addr/eax: (addr function)
15805         (lookup *esi *(esi+4))  # => eax
15806         # initialize vars
15807         (clear-stack %ebx)
15808         #
15809         (populate-mu-function-header %ecx %eax %ebx *(ebp+0xc) *(ebp+0x10))
15810         (populate-mu-function-body *(ebp+8) %eax %ebx *(ebp+0xc) *(ebp+0x10))
15811         # *curr-function = new-function
15812         8b/-> *esi 0/r32/eax
15813         89/<- *edi 0/r32/eax
15814         8b/-> *(esi+4) 0/r32/eax
15815         89/<- *(edi+4) 0/r32/eax
15816         # curr-function = &new-function->next
15817         # . var tmp/eax: (addr function) = lookup(new-function)
15818         (lookup *esi *(esi+4))  # => eax
15819         # . curr-function = &tmp->next
15820         8d/copy-address *(eax+0x20) 7/r32/edi  # Function-next
15821         # reclaim new-function
15822         81 0/subop/add %esp 8/imm32
15823         #
15824         e9/jump $parse-mu:line-loop/disp32
15825       }
15826       # if (slice-equal?(word-slice, "sig")) parse a function signature
15827       # Function signatures are for providing types to SubX functions.
15828       {
15829 $parse-mu:sig:
15830         (slice-equal? %edx "sig")  # => eax
15831         3d/compare-eax-and 0/imm32/false
15832         0f 84/jump-if-= break/disp32
15833         # edi = curr-function
15834         57/push-edi
15835         8b/-> *(ebp-4) 7/r32/edi
15836         # var new-function/esi: (handle function)
15837         68/push 0/imm32
15838         68/push 0/imm32
15839         89/<- %esi 4/r32/esp
15840         # populate-mu-function(line, in, vars, new-function)
15841         (allocate Heap *Function-size %esi)
15842         # var new-function-addr/eax: (addr function)
15843         (lookup *esi *(esi+4))  # => eax
15844         #
15845         (populate-mu-function-signature %ecx %eax *(ebp+0xc) *(ebp+0x10))
15846         # *curr-signature = new-function
15847         8b/-> *esi 0/r32/eax
15848         89/<- *edi 0/r32/eax
15849         8b/-> *(esi+4) 0/r32/eax
15850         89/<- *(edi+4) 0/r32/eax
15851         # curr-signature = &new-function->next
15852         # . var tmp/eax: (addr function) = lookup(new-function)
15853         (lookup *esi *(esi+4))  # => eax
15854         # . curr-function = &tmp->next
15855         8d/copy-address *(eax+0x20) 7/r32/edi  # Function-next
15856         # reclaim new-function
15857         81 0/subop/add %esp 8/imm32
15858         # save curr-function
15859         89/<- *(ebp-4) 7/r32/edi
15860         # restore edi
15861         5f/pop-to-edi
15862         #
15863         e9/jump $parse-mu:line-loop/disp32
15864       }
15865       # if (slice-equal?(word-slice, "type")) parse a type (struct/record) definition
15866       {
15867 $parse-mu:type:
15868         (slice-equal? %edx "type")  # => eax
15869         3d/compare-eax-and 0/imm32
15870         0f 84/jump-if-= break/disp32
15871         (next-mu-token %ecx %edx)
15872         # var type-id/eax: int
15873         (pos-or-insert-slice Type-id %edx)  # => eax
15874         # spill
15875         51/push-ecx
15876         # var new-type/ecx: (handle typeinfo)
15877         68/push 0/imm32
15878         68/push 0/imm32
15879         89/<- %ecx 4/r32/esp
15880         (find-or-create-typeinfo %eax %ecx)
15881         #
15882         (lookup *ecx *(ecx+4))  # => eax
15883         # TODO: ensure that 'line' has nothing else but '{'
15884 #? (dump-typeinfos "=== aaa\n")
15885         (populate-mu-type *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10))  # => eax
15886 #? (dump-typeinfos "=== zzz\n")
15887         # reclaim new-type
15888         81 0/subop/add %esp 8/imm32
15889         # restore
15890         59/pop-to-ecx
15891         e9/jump $parse-mu:line-loop/disp32
15892       }
15893       # otherwise abort
15894       e9/jump $parse-mu:error1/disp32
15895     } # end line loop
15896 $parse-mu:end:
15897     # . reclaim locals
15898     81 0/subop/add %esp 0x20c/imm32  # line
15899     81 0/subop/add %esp 0xc08/imm32  # vars
15900     81 0/subop/add %esp 8/imm32
15901     # . restore registers
15902     5f/pop-to-edi
15903     5e/pop-to-esi
15904     5b/pop-to-ebx
15905     5a/pop-to-edx
15906     59/pop-to-ecx
15907     58/pop-to-eax
15908     # . reclaim local
15909     81 0/subop/add %esp 4/imm32
15910     # . epilogue
15911     89/<- %esp 5/r32/ebp
15912     5d/pop-to-ebp
15913     c3/return
15914 
15915 $parse-mu:error1:
15916     # error("unexpected top-level command: " word-slice "\n")
15917     (write-buffered *(ebp+0xc) "unexpected top-level command: ")
15918     (write-slice-buffered *(ebp+0xc) %edx)
15919     (write-buffered *(ebp+0xc) "\n")
15920     (flush *(ebp+0xc))
15921     (stop *(ebp+0x10) 1)
15922     # never gets here
15923 
15924 $parse-mu:error2:
15925     # error(vars->top " vars not reclaimed after fn '" new-function->name "'\n")
15926     (write-int32-hex-buffered *(ebp+0xc) *ebx)
15927     (write-buffered *(ebp+0xc) " vars not reclaimed after fn '")
15928     (write-slice-buffered *(ebp+0xc) *eax)  # Function-name
15929     (write-buffered *(ebp+0xc) "'\n")
15930     (flush *(ebp+0xc))
15931     (stop *(ebp+0x10) 1)
15932     # never gets here
15933 
15934 # scenarios considered:
15935 # ✗ fn foo  # no block
15936 # ✓ fn foo {
15937 # ✗ fn foo { {
15938 # ✗ fn foo { }
15939 # ✗ fn foo { } {
15940 # ✗ fn foo x {
15941 # ✗ fn foo x: {
15942 # ✓ fn foo x: int {
15943 # ✓ fn foo x: int {
15944 # ✓ fn foo x: int -> _/eax: int {
15945 # TODO:
15946 #   disallow outputs of type `(... addr ...)`
15947 #   disallow inputs of type `(... addr ... addr ...)`
15948 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)
15949     # pseudocode:
15950     #   var word-slice: slice
15951     #   next-mu-token(first-line, word-slice)
15952     #   if slice-empty?(word-slice) abort
15953     #   assert(word-slice not in '{' '}' '->')
15954     #   out->name = slice-to-string(word-slice)
15955     #   ## inouts
15956     #   while true
15957     #     word-slice = next-mu-token(first-line)
15958     #     if slice-empty?(word-slice) abort
15959     #     if (word-slice == '{') goto done
15960     #     if (word-slice == '->') break
15961     #     assert(word-slice != '}')
15962     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
15963     #     assert(v->register == null)
15964     #     # v->block-depth is implicitly 0
15965     #     out->inouts = append(v, out->inouts)
15966     #     push(vars, {v, false})
15967     #   ## outputs
15968     #   while true
15969     #     word-slice = next-mu-token(first-line)
15970     #     if slice-empty?(word-slice) abort
15971     #     if (word-slice == '{') break
15972     #     assert(word-slice not in '}' '->')
15973     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
15974     #     assert(v->register != null)
15975     #     assert(v->name == "_")
15976     #     out->outputs = append(v, out->outputs)
15977     #   done:
15978     #
15979     # . prologue
15980     55/push-ebp
15981     89/<- %ebp 4/r32/esp
15982     # . save registers
15983     50/push-eax
15984     51/push-ecx
15985     52/push-edx
15986     53/push-ebx
15987     57/push-edi
15988     # edi = out
15989     8b/-> *(ebp+0xc) 7/r32/edi
15990     # var word-slice/ecx: slice
15991     68/push 0/imm32/end
15992     68/push 0/imm32/start
15993     89/<- %ecx 4/r32/esp
15994     # var v/ebx: (handle var)
15995     68/push 0/imm32
15996     68/push 0/imm32
15997     89/<- %ebx 4/r32/esp
15998     # read function name
15999     (next-mu-token *(ebp+8) %ecx)
16000     # error checking
16001     # if slice-empty?(word-slice) abort
16002     (slice-empty? %ecx)  # => eax
16003     3d/compare-eax-and 0/imm32/false
16004     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
16005     # if (word-slice == '{') abort
16006     (slice-equal? %ecx "{")   # => eax
16007     3d/compare-eax-and 0/imm32/false
16008     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
16009     # if (word-slice == '->') abort
16010     (slice-equal? %ecx "->")   # => eax
16011     3d/compare-eax-and 0/imm32/false
16012     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
16013     # if (word-slice == '}') abort
16014     (slice-equal? %ecx "}")   # => eax
16015     3d/compare-eax-and 0/imm32/false
16016     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
16017     # if word-slice already defined, abort
16018     (function-exists? %ecx)  # => eax
16019     3d/compare-eax-and 0/imm32/false
16020     0f 85/jump-if-!= $populate-mu-function-header:error-duplicate/disp32
16021     #
16022     (slice-starts-with? %ecx "break")  # => eax
16023     3d/compare-eax-and 0/imm32/false
16024     0f 85/jump-if-!= $populate-mu-function-header:error-break/disp32
16025     (slice-starts-with? %ecx "loop")  # => eax
16026     3d/compare-eax-and 0/imm32/false
16027     0f 85/jump-if-!= $populate-mu-function-header:error-loop/disp32
16028     (slice-equal? %ecx "lookup")  # => eax
16029     3d/compare-eax-and 0/imm32/false
16030     0f 85/jump-if-!= $populate-mu-function-header:error-lookup/disp32
16031     # save function name
16032     (slice-to-string Heap %ecx %edi)  # Function-name
16033     # save function inouts
16034     {
16035 $populate-mu-function-header:check-for-inout:
16036       (next-mu-token *(ebp+8) %ecx)
16037       # if slice-empty?(word-slice) abort
16038       (slice-empty? %ecx)  # => eax
16039       3d/compare-eax-and 0/imm32/false
16040       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
16041       # if (word-slice == '{') goto done
16042       (slice-equal? %ecx "{")   # => eax
16043       3d/compare-eax-and 0/imm32/false
16044       0f 85/jump-if-!= $populate-mu-function-header:done/disp32
16045       # if (word-slice == '->') break
16046       (slice-equal? %ecx "->")   # => eax
16047       3d/compare-eax-and 0/imm32/false
16048       0f 85/jump-if-!= break/disp32
16049       # if (word-slice == '}') abort
16050       (slice-equal? %ecx "}")   # => eax
16051       3d/compare-eax-and 0/imm32/false
16052       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
16053       # v = parse-var-with-type(word-slice, first-line)
16054       (lookup *edi *(edi+4))  # Function-name Function-name => eax
16055       (parse-var-with-type %ecx *(ebp+8) %ebx %eax *(ebp+0x14) *(ebp+0x18))
16056       # if (v->register != null) abort
16057       # . eax: (addr var) = lookup(v)
16058       (lookup *ebx *(ebx+4))  # => eax
16059       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
16060       0f 85/jump-if-!= $populate-mu-function-header:error2/disp32
16061       # if function name is not "main"
16062       #    and v->type contains an 'addr' anywhere except the start, abort
16063       {
16064         (lookup *edi *(edi+4))  # Function-name Function-name => eax
16065         (string-equal? %eax "main")  # => eax
16066         3d/compare-eax-and 0/imm32/false
16067         75/jump-if-!= break/disp8
16068         (lookup *ebx *(ebx+4))  # => eax
16069         (addr-payload-contains-addr? %eax)  # => eax
16070         3d/compare-eax-and 0/imm32/false
16071         0f 85/jump-if-!= $populate-mu-function-header:error-nested-addr-inout/disp32
16072       }
16073       # v->block-depth is implicitly 0
16074       #
16075       # out->inouts = append(v, out->inouts)
16076       8d/copy-address *(edi+8) 0/r32/eax  # Function-inouts
16077       (append-list Heap  *ebx *(ebx+4)  *(edi+8) *(edi+0xc)  %eax)  # Function-inouts, Function-inouts
16078       # push(vars, {v, false})
16079       (push *(ebp+0x10) *ebx)
16080       (push *(ebp+0x10) *(ebx+4))
16081       (push *(ebp+0x10) 0)  # false
16082       #
16083       e9/jump loop/disp32
16084     }
16085     # save function outputs
16086     {
16087 $populate-mu-function-header:check-for-out:
16088       (next-mu-token *(ebp+8) %ecx)
16089       # if slice-empty?(word-slice) abort
16090       (slice-empty? %ecx)  # => eax
16091       3d/compare-eax-and 0/imm32/false
16092       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
16093       # if (word-slice == '{') break
16094       (slice-equal? %ecx "{")   # => eax
16095       3d/compare-eax-and 0/imm32/false
16096       0f 85/jump-if-!= break/disp32
16097       # if (word-slice == '->') abort
16098       (slice-equal? %ecx "->")   # => eax
16099       3d/compare-eax-and 0/imm32/false
16100       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
16101       # if (word-slice == '}') abort
16102       (slice-equal? %ecx "}")   # => eax
16103       3d/compare-eax-and 0/imm32/false
16104       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
16105       # v = parse-var-with-type(word-slice, first-line)
16106       (lookup *edi *(edi+4))  # Function-name Function-name => eax
16107       (parse-var-with-type %ecx *(ebp+8) %ebx %eax *(ebp+0x14) *(ebp+0x18))
16108       # assert(var->register != null)
16109       # . eax: (addr var) = lookup(v)
16110       (lookup *ebx *(ebx+4))  # => eax
16111       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
16112       0f 84/jump-if-= $populate-mu-function-header:error3/disp32
16113       # if (var->name != "_") abort
16114       (lookup *eax *(eax+4))  # Var-name Var-name => eax
16115       (string-equal? %eax "_")  # => eax
16116       3d/compare-eax-and 0/imm32/false
16117       0f 84/jump-if-= $populate-mu-function-header:error4/disp32
16118       # if v->type is an addr, abort
16119       (lookup *ebx *(ebx+4))  # => eax
16120       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
16121       (mu-addr-type? %eax)  # => eax
16122       3d/compare-eax-and 0/imm32/false
16123       0f 85/jump-if-!= $populate-mu-function-header:error-addr-output/disp32
16124       # out->outputs = append(v, out->outputs)
16125       8d/copy-address *(edi+0x10) 0/r32/eax  # Function-outputs
16126       (append-list Heap  *ebx *(ebx+4)  *(edi+0x10) *(edi+0x14)  %eax)  # Function-outputs, Function-outputs
16127       #
16128       e9/jump loop/disp32
16129     }
16130 $populate-mu-function-header:done:
16131     (check-no-tokens-left *(ebp+8))
16132 $populate-mu-function-header:end:
16133     # . reclaim locals
16134     81 0/subop/add %esp 0x10/imm32
16135     # . restore registers
16136     5f/pop-to-edi
16137     5b/pop-to-ebx
16138     5a/pop-to-edx
16139     59/pop-to-ecx
16140     58/pop-to-eax
16141     # . epilogue
16142     89/<- %esp 5/r32/ebp
16143     5d/pop-to-ebp
16144     c3/return
16145 
16146 $populate-mu-function-header:error1:
16147     # error("function header not in form 'fn <name> {'")
16148     (write-buffered *(ebp+0x14) "function header not in form 'fn <name> [inouts] [-> outputs] {' -- '")
16149     (flush *(ebp+0x14))
16150     (rewind-stream *(ebp+8))
16151     (write-stream-data *(ebp+0x14) *(ebp+8))
16152     (write-buffered *(ebp+0x14) "'\n")
16153     (flush *(ebp+0x14))
16154     (stop *(ebp+0x18) 1)
16155     # never gets here
16156 
16157 $populate-mu-function-header:error2:
16158     # error("fn " fn ": function inout '" var "' cannot be in a register")
16159     (write-buffered *(ebp+0x14) "fn ")
16160     50/push-eax
16161     (lookup *edi *(edi+4))  # Function-name Function-name => eax
16162     (write-buffered *(ebp+0x14) %eax)
16163     58/pop-to-eax
16164     (write-buffered *(ebp+0x14) ": function inout '")
16165     (lookup *eax *(eax+4))  # Var-name Var-name => eax
16166     (write-buffered *(ebp+0x14) %eax)
16167     (write-buffered *(ebp+0x14) "' cannot be in a register")
16168     (flush *(ebp+0x14))
16169     (stop *(ebp+0x18) 1)
16170     # never gets here
16171 
16172 $populate-mu-function-header:error3:
16173     # error("fn " fn ": function output '" var "' must be in a register")
16174     (write-buffered *(ebp+0x14) "fn ")
16175     50/push-eax
16176     (lookup *edi *(edi+4))  # Function-name Function-name => eax
16177     (write-buffered *(ebp+0x14) %eax)
16178     58/pop-to-eax
16179     (write-buffered *(ebp+0x14) ": function output '")
16180     (lookup *ebx *(ebx+4))  # => eax
16181     (lookup *eax *(eax+4))  # Var-name Var-name => eax
16182     (write-buffered *(ebp+0x14) %eax)
16183     (write-buffered *(ebp+0x14) "' must be in a register, in instruction '")
16184     (rewind-stream *(ebp+8))
16185     (write-stream-data *(ebp+0x14) *(ebp+8))
16186     (write-buffered *(ebp+0x14) "'\n")
16187     (flush *(ebp+0x14))
16188     (stop *(ebp+0x18) 1)
16189     # never gets here
16190 
16191 $populate-mu-function-header:error4:
16192     # error("fn " fn ": function outputs cannot be named; rename '" var "' in the header to '_'")
16193     (write-buffered *(ebp+0x14) "fn ")
16194     50/push-eax
16195     (lookup *edi *(edi+4))  # Function-name Function-name => eax
16196     (write-buffered *(ebp+0x14) %eax)
16197     58/pop-to-eax
16198     (write-buffered *(ebp+0x14) ": function outputs cannot be named; rename '")
16199     (lookup *ebx *(ebx+4))  # => eax
16200     (lookup *eax *(eax+4))  # Var-name Var-name => eax
16201     (write-buffered *(ebp+0x14) %eax)
16202     (write-buffered *(ebp+0x14) "' in the header to '_'\n")
16203     (flush *(ebp+0x14))
16204     (stop *(ebp+0x18) 1)
16205     # never gets here
16206 
16207 $populate-mu-function-header:error-duplicate:
16208     (write-buffered *(ebp+0x14) "fn ")
16209     (write-slice-buffered *(ebp+0x14) %ecx)
16210     (write-buffered *(ebp+0x14) " defined more than once\n")
16211     (flush *(ebp+0x14))
16212     (stop *(ebp+0x18) 1)
16213     # never gets here
16214 
16215 $populate-mu-function-header:error-break:
16216     (write-buffered *(ebp+0x14) "Sorry, I've reserved all function names starting with 'break' for now. Please contact mu@akkartik.com.\n")
16217     (flush *(ebp+0x14))
16218     (stop *(ebp+0x18) 1)
16219     # never gets here
16220 
16221 $populate-mu-function-header:error-loop:
16222     (write-buffered *(ebp+0x14) "Sorry, I've reserved all function names starting with 'loop' for now. Please contact mu@akkartik.com.\n")
16223     (flush *(ebp+0x14))
16224     (stop *(ebp+0x18) 1)
16225     # never gets here
16226 
16227 $populate-mu-function-header:error-lookup:
16228     (write-buffered *(ebp+0x14) "cannot define a function called 'lookup'\n")
16229     (flush *(ebp+0x14))
16230     (stop *(ebp+0x18) 1)
16231     # never gets here
16232 
16233 $populate-mu-function-header:error-addr-output:
16234     # error("fn " fn ": output cannot have an addr type; that could allow unsafe addresses to escape the function")
16235     (write-buffered *(ebp+0x14) "fn ")
16236     50/push-eax
16237     (lookup *edi *(edi+4))  # Function-name Function-name => eax
16238     (write-buffered *(ebp+0x14) %eax)
16239     58/pop-to-eax
16240     (write-buffered *(ebp+0x14) ": output cannot have an addr type; that could allow unsafe addresses to escape the function\n")
16241     (flush *(ebp+0x14))
16242     (stop *(ebp+0x18) 1)
16243     # never gets here
16244 
16245 $populate-mu-function-header:error-nested-addr-inout:
16246     # error("fn " fn ": inout '" var "' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function")
16247     (write-buffered *(ebp+0x14) "fn ")
16248     (lookup *edi *(edi+4))  # Function-name Function-name => eax
16249     (write-buffered *(ebp+0x14) %eax)
16250     (write-buffered *(ebp+0x14) ": inout '")
16251     (lookup *ebx *(ebx+4))  # => eax
16252     (lookup *eax *(eax+4))  # Var-name Var-name => eax
16253     (write-buffered *(ebp+0x14) %eax)
16254     (write-buffered *(ebp+0x14) "' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function\n")
16255     (flush *(ebp+0x14))
16256     (stop *(ebp+0x18) 1)
16257     # never gets here
16258 
16259 # scenarios considered:
16260 # ✓ fn foo
16261 # ✗ fn foo {
16262 # ✓ fn foo x
16263 # ✓ fn foo x: int
16264 # ✓ fn foo x: int -> _/eax: int
16265 # TODO:
16266 #   disallow outputs of type `(... addr ...)`
16267 #   disallow inputs of type `(... addr ... addr ...)`
16268 populate-mu-function-signature:  # first-line: (addr stream byte), out: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
16269     # pseudocode:
16270     #   var word-slice: slice
16271     #   next-mu-token(first-line, word-slice)
16272     #   assert(word-slice not in '{' '}' '->')
16273     #   out->name = slice-to-string(word-slice)
16274     #   ## inouts
16275     #   while true
16276     #     word-slice = next-mu-token(first-line)
16277     #     if slice-empty?(word-slice) break
16278     #     if (word-slice == '->') break
16279     #     assert(word-slice not in '{' '}')
16280     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
16281     #     assert(v->register == null)
16282     #     # v->block-depth is implicitly 0
16283     #     out->inouts = append(v, out->inouts)
16284     #   ## outputs
16285     #   while true
16286     #     word-slice = next-mu-token(first-line)
16287     #     if slice-empty?(word-slice) break
16288     #     assert(word-slice not in '{' '}' '->')
16289     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
16290     #     assert(v->register != null)
16291     #     out->outputs = append(v, out->outputs)
16292     #
16293     # . prologue
16294     55/push-ebp
16295     89/<- %ebp 4/r32/esp
16296     # . save registers
16297     50/push-eax
16298     51/push-ecx
16299     52/push-edx
16300     53/push-ebx
16301     57/push-edi
16302     # edi = out
16303     8b/-> *(ebp+0xc) 7/r32/edi
16304     # var word-slice/ecx: slice
16305     68/push 0/imm32/end
16306     68/push 0/imm32/start
16307     89/<- %ecx 4/r32/esp
16308     # var v/ebx: (handle var)
16309     68/push 0/imm32
16310     68/push 0/imm32
16311     89/<- %ebx 4/r32/esp
16312     # read function name
16313     (next-mu-token *(ebp+8) %ecx)
16314     # error checking
16315     # if (word-slice == '{') abort
16316     (slice-equal? %ecx "{")   # => eax
16317     3d/compare-eax-and 0/imm32/false
16318     0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
16319     # if (word-slice == '->') abort
16320     (slice-equal? %ecx "->")   # => eax
16321     3d/compare-eax-and 0/imm32/false
16322     0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
16323     # if (word-slice == '}') abort
16324     (slice-equal? %ecx "}")   # => eax
16325     3d/compare-eax-and 0/imm32/false
16326     0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
16327     # if word-slice already defined, abort
16328     (function-exists? %ecx)  # => eax
16329     3d/compare-eax-and 0/imm32/false
16330     0f 85/jump-if-!= $populate-mu-function-signature:error-duplicate/disp32
16331     #
16332     (slice-starts-with? %ecx "break")  # => eax
16333     3d/compare-eax-and 0/imm32/false
16334     0f 85/jump-if-!= $populate-mu-function-signature:error-break/disp32
16335     (slice-starts-with? %ecx "loop")  # => eax
16336     3d/compare-eax-and 0/imm32/false
16337     0f 85/jump-if-!= $populate-mu-function-signature:error-loop/disp32
16338     # save function name
16339     (slice-to-string Heap %ecx %edi)  # Function-name
16340     # save function inouts
16341     {
16342 $populate-mu-function-signature:check-for-inout:
16343       (next-mu-token *(ebp+8) %ecx)
16344       (slice-empty? %ecx)  # => eax
16345       3d/compare-eax-and 0/imm32/false
16346       0f 85/jump-if-!= break/disp32
16347       # if (word-slice == '->') break
16348       (slice-equal? %ecx "->")   # => eax
16349       3d/compare-eax-and 0/imm32/false
16350       0f 85/jump-if-!= break/disp32
16351       # if (word-slice == '{') abort
16352       (slice-equal? %ecx "{")   # => eax
16353       3d/compare-eax-and 0/imm32/false
16354       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
16355       # if (word-slice == '}') abort
16356       (slice-equal? %ecx "}")   # => eax
16357       3d/compare-eax-and 0/imm32/false
16358       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
16359       # v = parse-var-with-type(word-slice, first-line)
16360       (lookup *edi *(edi+4))  # Function-name Function-name => eax
16361       (parse-var-with-type %ecx *(ebp+8) %ebx %eax *(ebp+0x10) *(ebp+0x14))
16362       # if (v->register != null) abort
16363       # . eax: (addr var) = lookup(v)
16364       (lookup *ebx *(ebx+4))  # => eax
16365       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
16366       0f 85/jump-if-!= $populate-mu-function-signature:error2/disp32
16367       # if function name is not "main"
16368       #    and v->type contains an 'addr' anywhere except the start, abort
16369       {
16370         (lookup *edi *(edi+4))  # Function-name Function-name => eax
16371         (string-equal? %eax "main")  # => eax
16372         3d/compare-eax-and 0/imm32/false
16373         75/jump-if-!= break/disp8
16374         (lookup *ebx *(ebx+4))  # => eax
16375         (addr-payload-contains-addr? %eax)  # => eax
16376         3d/compare-eax-and 0/imm32/false
16377         0f 85/jump-if-!= $populate-mu-function-signature:error-nested-addr-inout/disp32
16378       }
16379       # assert(v->register == null)
16380       # . eax: (addr var) = lookup(v)
16381       (lookup *ebx *(ebx+4))  # => eax
16382       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
16383       0f 85/jump-if-!= $populate-mu-function-signature:error2/disp32
16384       # v->block-depth is implicitly 0
16385       #
16386       # out->inouts = append(v, out->inouts)
16387       8d/copy-address *(edi+8) 0/r32/eax  # Function-inouts
16388       (append-list Heap  *ebx *(ebx+4)  *(edi+8) *(edi+0xc)  %eax)  # Function-inouts, Function-inouts
16389       #
16390       e9/jump loop/disp32
16391     }
16392     # save function outputs
16393     {
16394 $populate-mu-function-signature:check-for-out:
16395       (next-mu-token *(ebp+8) %ecx)
16396       (slice-empty? %ecx)  # => eax
16397       3d/compare-eax-and 0/imm32/false
16398       0f 85/jump-if-!= break/disp32
16399       # if (word-slice == '{') abort
16400       (slice-equal? %ecx "{")   # => eax
16401       3d/compare-eax-and 0/imm32/false
16402       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
16403       # if (word-slice == '->') abort
16404       (slice-equal? %ecx "->")   # => eax
16405       3d/compare-eax-and 0/imm32/false
16406       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
16407       # if (word-slice == '}') abort
16408       (slice-equal? %ecx "}")   # => eax
16409       3d/compare-eax-and 0/imm32/false
16410       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
16411       # v = parse-var-with-type(word-slice, first-line)
16412       (lookup *edi *(edi+4))  # Function-name Function-name => eax
16413       (parse-var-with-type %ecx *(ebp+8) %ebx %eax *(ebp+0x10) *(ebp+0x14))
16414       # assert(var->register != null)
16415       # . eax: (addr var) = lookup(v)
16416       (lookup *ebx *(ebx+4))  # => eax
16417       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
16418       0f 84/jump-if-= $populate-mu-function-signature:error3/disp32
16419       # if (var->name != "_") abort
16420       (lookup *eax *(eax+4))  # Var-name Var-name => eax
16421       (string-equal? %eax "_")  # => eax
16422       3d/compare-eax-and 0/imm32/false
16423       0f 84/jump-if-= $populate-mu-function-signature:error4/disp32
16424       # if function name is not "lookup"
16425       #    and v->type is an addr, abort
16426       {
16427         (lookup *edi *(edi+4))  # Function-name Function-name => eax
16428         (string-equal? %eax "lookup")  # => eax
16429         3d/compare-eax-and 0/imm32/false
16430         75/jump-if-!= break/disp8
16431         (lookup *ebx *(ebx+4))  # => eax
16432         (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
16433         (mu-addr-type? %eax)  # => eax
16434         3d/compare-eax-and 0/imm32/false
16435         0f 85/jump-if-!= $populate-mu-function-signature:error-addr-output/disp32
16436       }
16437       # out->outputs = append(v, out->outputs)
16438       8d/copy-address *(edi+0x10) 0/r32/eax  # Function-outputs
16439       (append-list Heap  *ebx *(ebx+4)  *(edi+0x10) *(edi+0x14)  %eax)  # Function-outputs, Function-outputs
16440       #
16441       e9/jump loop/disp32
16442     }
16443 $populate-mu-function-signature:done:
16444     (check-no-tokens-left *(ebp+8))
16445 $populate-mu-function-signature:end:
16446     # . reclaim locals
16447     81 0/subop/add %esp 0x10/imm32
16448     # . restore registers
16449     5f/pop-to-edi
16450     5b/pop-to-ebx
16451     5a/pop-to-edx
16452     59/pop-to-ecx
16453     58/pop-to-eax
16454     # . epilogue
16455     89/<- %esp 5/r32/ebp
16456     5d/pop-to-ebp
16457     c3/return
16458 
16459 $populate-mu-function-signature:error1:
16460     # error("function signature not in form 'fn <name> {'")
16461     (write-buffered *(ebp+0x10) "function signature not in form 'fn <name> [inouts] [-> outputs] {' -- '")
16462     (flush *(ebp+0x10))
16463     (rewind-stream *(ebp+8))
16464     (write-stream-data *(ebp+0x10) *(ebp+8))
16465     (write-buffered *(ebp+0x10) "'\n")
16466     (flush *(ebp+0x10))
16467     (stop *(ebp+0x14) 1)
16468     # never gets here
16469 
16470 $populate-mu-function-signature:error2:
16471     # error("fn " fn ": function inout '" var "' cannot be in a register")
16472     (write-buffered *(ebp+0x10) "fn ")
16473     50/push-eax
16474     (lookup *edi *(edi+4))  # Function-name Function-name => eax
16475     (write-buffered *(ebp+0x10) %eax)
16476     58/pop-to-eax
16477     (write-buffered *(ebp+0x10) ": function inout '")
16478     (lookup *eax *(eax+4))  # Var-name Var-name => eax
16479     (write-buffered *(ebp+0x10) %eax)
16480     (write-buffered *(ebp+0x10) "' cannot be in a register")
16481     (flush *(ebp+0x10))
16482     (stop *(ebp+0x14) 1)
16483     # never gets here
16484 
16485 $populate-mu-function-signature:error3:
16486     # error("fn " fn ": function output '" var "' must be in a register")
16487     (write-buffered *(ebp+0x10) "fn ")
16488     50/push-eax
16489     (lookup *edi *(edi+4))  # Function-name Function-name => eax
16490     (write-buffered *(ebp+0x10) %eax)
16491     58/pop-to-eax
16492     (write-buffered *(ebp+0x10) ": function output '")
16493     (lookup *ebx *(ebx+4))  # => eax
16494     (lookup *eax *(eax+4))  # Var-name Var-name => eax
16495     (write-buffered *(ebp+0x10) %eax)
16496     (write-buffered *(ebp+0x10) "' must be in a register, in instruction '")
16497     (rewind-stream *(ebp+8))
16498     (write-stream-data *(ebp+0x10) *(ebp+8))
16499     (write-buffered *(ebp+0x10) "'\n")
16500     (flush *(ebp+0x10))
16501     (stop *(ebp+0x14) 1)
16502     # never gets here
16503 
16504 $populate-mu-function-signature:error4:
16505     # error("fn " fn ": function outputs cannot be named; rename '" var "' in the header to '_'")
16506     (write-buffered *(ebp+0x10) "fn ")
16507     50/push-eax
16508     (lookup *edi *(edi+4))  # Function-name Function-name => eax
16509     (write-buffered *(ebp+0x10) %eax)
16510     58/pop-to-eax
16511     (write-buffered *(ebp+0x10) ": function outputs cannot be named; rename '")
16512     (lookup *ebx *(ebx+4))  # => eax
16513     (lookup *eax *(eax+4))  # Var-name Var-name => eax
16514     (write-buffered *(ebp+0x10) %eax)
16515     (write-buffered *(ebp+0x10) "' in the header to '_'\n")
16516     (flush *(ebp+0x10))
16517     (stop *(ebp+0x14) 1)
16518     # never gets here
16519 
16520 $populate-mu-function-signature:error-duplicate:
16521     (write-buffered *(ebp+0x10) "fn ")
16522     (write-slice-buffered *(ebp+0x10) %ecx)
16523     (write-buffered *(ebp+0x10) " defined more than once\n")
16524     (flush *(ebp+0x10))
16525     (stop *(ebp+0x14) 1)
16526     # never gets here
16527 
16528 $populate-mu-function-signature:error-break:
16529     (write-buffered *(ebp+0x10) "Sorry, I've reserved all function names starting with 'break' for now. Please contact mu@akkartik.com.\n")
16530     (flush *(ebp+0x10))
16531     (stop *(ebp+0x14) 1)
16532     # never gets here
16533 
16534 $populate-mu-function-signature:error-loop:
16535     (write-buffered *(ebp+0x10) "Sorry, I've reserved all function names starting with 'loop' for now. Please contact mu@akkartik.com.\n")
16536     (flush *(ebp+0x10))
16537     (stop *(ebp+0x14) 1)
16538     # never gets here
16539 
16540 $populate-mu-function-signature:error-addr-output:
16541     # error("fn " fn ": output cannot have an addr type; that could allow unsafe addresses to escape the function")
16542     (write-buffered *(ebp+0x10) "fn ")
16543     50/push-eax
16544     (lookup *edi *(edi+4))  # Function-name Function-name => eax
16545     (write-buffered *(ebp+0x10) %eax)
16546     58/pop-to-eax
16547     (write-buffered *(ebp+0x10) ": output cannot have an addr type; that could allow unsafe addresses to escape the function\n")
16548     (flush *(ebp+0x10))
16549     (stop *(ebp+0x14) 1)
16550     # never gets here
16551 
16552 $populate-mu-function-signature:error-nested-addr-inout:
16553     # error("fn " fn ": inout '" var "' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function")
16554     (write-buffered *(ebp+0x10) "fn ")
16555     (lookup *edi *(edi+4))  # Function-name Function-name => eax
16556     (write-buffered *(ebp+0x10) %eax)
16557     (write-buffered *(ebp+0x10) ": inout '")
16558     (lookup *ebx *(ebx+4))  # => eax
16559     (lookup *eax *(eax+4))  # Var-name Var-name => eax
16560     (write-buffered *(ebp+0x10) %eax)
16561     (write-buffered *(ebp+0x10) "' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function\n")
16562     (flush *(ebp+0x10))
16563     (stop *(ebp+0x14) 1)
16564     # never gets here
16565 
16566 addr-payload-contains-addr?:  # v: (addr var) -> result/eax: boolean
16567     # . prologue
16568     55/push-ebp
16569     89/<- %ebp 4/r32/esp
16570     # var t/eax: (addr type-tree) = v->type
16571     8b/-> *(ebp+8) 0/r32/eax
16572     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
16573     # if t->right contains addr, return true
16574     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
16575     (type-tree-contains? %eax 2)  # addr => eax
16576     # we don't have to look at t->left as long as it's guaranteed to be an atom
16577 $addr-payload-contains-addr?:end:
16578     # . epilogue
16579     89/<- %esp 5/r32/ebp
16580     5d/pop-to-ebp
16581     c3/return
16582 
16583 type-tree-contains?:  # t: (addr type-tree), n: type-id -> result/eax: boolean
16584     # . prologue
16585     55/push-ebp
16586     89/<- %ebp 4/r32/esp
16587     # . save registers
16588     51/push-ecx
16589     # if t is null, return false
16590     8b/-> *(ebp+8) 0/r32/eax
16591     3d/compare-eax-and 0/imm32
16592     0f 84/jump-if-= $type-tree-contains?:end/disp32  # eax changes type
16593     # if t is an atom, return (t->value == n)
16594     81 7/subop/compare *eax 0/imm32/false
16595     {
16596       74/jump-if-= break/disp8
16597       8b/-> *(ebp+0xc) 1/r32/ecx
16598       39/compare *(eax+4) 1/r32/ecx  # Type-tree-value
16599       0f 94/set-if-= %al
16600       81 4/subop/and %eax 0xff/imm32
16601       eb/jump $type-tree-contains?:end/disp8
16602     }
16603     # if t->left contains n, return true
16604     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
16605     (type-tree-contains? %eax *(ebp+0xc))  # => eax
16606     3d/compare-eax-and 0/imm32/false
16607     75/jump-if-!= $type-tree-contains?:end/disp8
16608     # otherwise return whether t->right contains n
16609     8b/-> *(ebp+8) 0/r32/eax
16610     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
16611     (type-tree-contains? %eax *(ebp+0xc))  # => eax
16612 $type-tree-contains?:end:
16613     # . restore registers
16614     59/pop-to-ecx
16615     # . epilogue
16616     89/<- %esp 5/r32/ebp
16617     5d/pop-to-ebp
16618     c3/return
16619 
16620 function-exists?:  # s: (addr slice) -> result/eax: boolean
16621     # . prologue
16622     55/push-ebp
16623     89/<- %ebp 4/r32/esp
16624     # . save registers
16625     51/push-ecx
16626     # var curr/ecx: (addr function) = functions
16627     (lookup *_Program-functions *_Program-functions->payload)  # => eax
16628     89/<- %ecx 0/r32/eax
16629     {
16630       # if (curr == null) break
16631       81 7/subop/compare %ecx 0/imm32
16632       74/jump-if-= break/disp8
16633       # if (curr->name == s) return true
16634       {
16635         (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
16636         (slice-equal? *(ebp+8) %eax)  # => eax
16637         3d/compare-eax-and 0/imm32/false
16638         74/jump-if-= break/disp8
16639         b8/copy-to-eax 1/imm32/true
16640         e9/jump $function-exists?:end/disp32
16641       }
16642       # curr = curr->next
16643       (lookup *(ecx+0x20) *(ecx+0x24))  # Function-next Function-next => eax
16644       89/<- %ecx 0/r32/eax
16645       #
16646       eb/jump loop/disp8
16647     }
16648     # var curr/ecx: (addr function) = signatures
16649     (lookup *_Program-signatures *_Program-signatures->payload)  # => eax
16650     89/<- %ecx 0/r32/eax
16651     {
16652       # if (curr == null) break
16653       81 7/subop/compare %ecx 0/imm32
16654       74/jump-if-= break/disp8
16655       # if (curr->name == s) return true
16656       {
16657         (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
16658         (slice-equal? *(ebp+8) %eax)  # => eax
16659         3d/compare-eax-and 0/imm32/false
16660         74/jump-if-= break/disp8
16661         b8/copy-to-eax 1/imm32/true
16662         eb/jump $function-exists?:end/disp8
16663       }
16664       # curr = curr->next
16665       (lookup *(ecx+0x20) *(ecx+0x24))  # Function-next Function-next => eax
16666       89/<- %ecx 0/r32/eax
16667       #
16668       eb/jump loop/disp8
16669     }
16670     # return false
16671     b8/copy-to-eax 0/imm32/false
16672 $function-exists?:end:
16673     # . restore registers
16674     59/pop-to-ecx
16675     # . epilogue
16676     89/<- %esp 5/r32/ebp
16677     5d/pop-to-ebp
16678     c3/return
16679 
16680 test-function-header-with-arg:
16681     # . prologue
16682     55/push-ebp
16683     89/<- %ebp 4/r32/esp
16684     # setup
16685     8b/-> *Primitive-type-ids 0/r32/eax
16686     89/<- *Type-id 0/r32/eax  # stream-write
16687     c7 0/subop/copy *_Program-functions 0/imm32
16688     c7 0/subop/copy *_Program-functions->payload 0/imm32
16689     c7 0/subop/copy *_Program-types 0/imm32
16690     c7 0/subop/copy *_Program-types->payload 0/imm32
16691     c7 0/subop/copy *_Program-signatures 0/imm32
16692     c7 0/subop/copy *_Program-signatures->payload 0/imm32
16693     (clear-stream _test-input-stream)
16694     (write _test-input-stream "foo n: int {\n")
16695     # var result/ecx: function
16696     2b/subtract *Function-size 4/r32/esp
16697     89/<- %ecx 4/r32/esp
16698     (zero-out %ecx *Function-size)
16699     # var vars/ebx: (stack live-var 16)
16700     81 5/subop/subtract %esp 0xc0/imm32
16701     68/push 0xc0/imm32/size
16702     68/push 0/imm32/top
16703     89/<- %ebx 4/r32/esp
16704     # convert
16705     (populate-mu-function-header _test-input-stream %ecx %ebx Stderr 0)
16706     # check result->name
16707     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
16708     (check-strings-equal %eax "foo" "F - test-function-header-with-arg/name")
16709     # var v/edx: (addr var) = result->inouts->value
16710     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
16711     (lookup *eax *(eax+4))  # List-value List-value => eax
16712     89/<- %edx 0/r32/eax
16713     # check v->name
16714     (lookup *edx *(edx+4))  # Var-name Var-name => eax
16715     (check-strings-equal %eax "n" "F - test-function-header-with-arg/inout:0")
16716     # check v->type
16717     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
16718     (check-ints-equal *eax 1 "F - test-function-header-with-arg/inout:0/type:0")  # Type-tree-is-atom
16719     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-arg/inout:0/type:1")  # Type-tree-value
16720     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-arg/inout:0/type:2")  # Type-tree-right
16721     # . epilogue
16722     89/<- %esp 5/r32/ebp
16723     5d/pop-to-ebp
16724     c3/return
16725 
16726 test-function-header-with-multiple-args:
16727     # . prologue
16728     55/push-ebp
16729     89/<- %ebp 4/r32/esp
16730     # setup
16731     8b/-> *Primitive-type-ids 0/r32/eax
16732     89/<- *Type-id 0/r32/eax  # stream-write
16733     c7 0/subop/copy *_Program-functions 0/imm32
16734     c7 0/subop/copy *_Program-functions->payload 0/imm32
16735     c7 0/subop/copy *_Program-types 0/imm32
16736     c7 0/subop/copy *_Program-types->payload 0/imm32
16737     c7 0/subop/copy *_Program-signatures 0/imm32
16738     c7 0/subop/copy *_Program-signatures->payload 0/imm32
16739     (clear-stream _test-input-stream)
16740     (write _test-input-stream "foo a: int, b: int c: int {\n")
16741     # result/ecx: function
16742     2b/subtract *Function-size 4/r32/esp
16743     89/<- %ecx 4/r32/esp
16744     (zero-out %ecx *Function-size)
16745     # var vars/ebx: (stack live-var 16)
16746     81 5/subop/subtract %esp 0xc0/imm32
16747     68/push 0xc0/imm32/size
16748     68/push 0/imm32/top
16749     89/<- %ebx 4/r32/esp
16750     # convert
16751     (populate-mu-function-header _test-input-stream %ecx %ebx Stderr 0)
16752     # check result->name
16753     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
16754     (check-strings-equal %eax "foo" "F - test-function-header-with-multiple-args/name")
16755     # var inouts/edx: (addr list var) = lookup(result->inouts)
16756     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
16757     89/<- %edx 0/r32/eax
16758 $test-function-header-with-multiple-args:inout0:
16759     # var v/ebx: (addr var) = lookup(inouts->value)
16760     (lookup *edx *(edx+4))  # List-value List-value => eax
16761     89/<- %ebx 0/r32/eax
16762     # check v->name
16763     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
16764     (check-strings-equal %eax "a" "F - test-function-header-with-multiple-args/inout:0")  # Var-name
16765     # check v->type
16766     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
16767     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args/inout:0/type:0")  # Type-tree-is-atom
16768     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args/inout:0/type:1")  # Type-tree-value
16769     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args/inout:0/type:2")  # Type-tree-right
16770 $test-function-header-with-multiple-args:inout1:
16771     # inouts = lookup(inouts->next)
16772     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
16773     89/<- %edx 0/r32/eax
16774     # v = lookup(inouts->value)
16775     (lookup *edx *(edx+4))  # List-value List-value => eax
16776     89/<- %ebx 0/r32/eax
16777     # check v->name
16778     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
16779     (check-strings-equal %eax "b" "F - test-function-header-with-multiple-args/inout:1")  # Var-name
16780     # check v->type
16781     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
16782     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args/inout:1/type:0")  # Type-tree-is-atom
16783     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args/inout:1/type:1")  # Type-tree-value
16784     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args/inout:1/type:2")  # Type-tree-right
16785 $test-function-header-with-multiple-args:inout2:
16786     # inouts = lookup(inouts->next)
16787     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
16788     89/<- %edx 0/r32/eax
16789     # v = lookup(inouts->value)
16790     (lookup *edx *(edx+4))  # List-value List-value => eax
16791     89/<- %ebx 0/r32/eax
16792     # check v->name
16793     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
16794     (check-strings-equal %eax "c" "F - test-function-header-with-multiple-args/inout:2")  # Var-name
16795     # check v->type
16796     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
16797     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args/inout:2/type:0")  # Type-tree-is-atom
16798     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args/inout:2/type:1")  # Type-tree-value
16799     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args/inout:2/type:2")  # Type-tree-right
16800     # . epilogue
16801     89/<- %esp 5/r32/ebp
16802     5d/pop-to-ebp
16803     c3/return
16804 
16805 test-function-header-with-multiple-args-and-outputs:
16806     # . prologue
16807     55/push-ebp
16808     89/<- %ebp 4/r32/esp
16809     # setup
16810     8b/-> *Primitive-type-ids 0/r32/eax
16811     89/<- *Type-id 0/r32/eax  # stream-write
16812     c7 0/subop/copy *_Program-functions 0/imm32
16813     c7 0/subop/copy *_Program-functions->payload 0/imm32
16814     c7 0/subop/copy *_Program-types 0/imm32
16815     c7 0/subop/copy *_Program-types->payload 0/imm32
16816     c7 0/subop/copy *_Program-signatures 0/imm32
16817     c7 0/subop/copy *_Program-signatures->payload 0/imm32
16818     (clear-stream _test-input-stream)
16819     (write _test-input-stream "foo a: int, b: int, c: int -> _/ecx: int _/edx: int {\n")
16820     # result/ecx: function
16821     2b/subtract *Function-size 4/r32/esp
16822     89/<- %ecx 4/r32/esp
16823     (zero-out %ecx *Function-size)
16824     # var vars/ebx: (stack live-var 16)
16825     81 5/subop/subtract %esp 0xc0/imm32
16826     68/push 0xc0/imm32/size
16827     68/push 0/imm32/top
16828     89/<- %ebx 4/r32/esp
16829     # convert
16830     (populate-mu-function-header _test-input-stream %ecx %ebx Stderr 0)
16831     # check result->name
16832     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
16833     (check-strings-equal %eax "foo" "F - test-function-header-with-multiple-args-and-outputs/name")
16834     # var inouts/edx: (addr list var) = lookup(result->inouts)
16835     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
16836     89/<- %edx 0/r32/eax
16837 $test-function-header-with-multiple-args-and-outputs:inout0:
16838     # var v/ebx: (addr var) = lookup(inouts->value)
16839     (lookup *edx *(edx+4))  # List-value List-value => eax
16840     89/<- %ebx 0/r32/eax
16841     # check v->name
16842     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
16843     (check-strings-equal %eax "a" "F - test-function-header-with-multiple-args-and-outputs/inout:0")
16844     # check v->type
16845     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
16846     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:0")  # Type-tree-is-atom
16847     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:1")  # Type-tree-value
16848     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:2")  # Type-tree-right
16849 $test-function-header-with-multiple-args-and-outputs:inout1:
16850     # inouts = lookup(inouts->next)
16851     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
16852     89/<- %edx 0/r32/eax
16853     # v = lookup(inouts->value)
16854     (lookup *edx *(edx+4))  # List-value List-value => eax
16855     89/<- %ebx 0/r32/eax
16856     # check v->name
16857     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
16858     (check-strings-equal %eax "b" "F - test-function-header-with-multiple-args-and-outputs/inout:1")
16859     # check v->type
16860     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
16861     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:0")  # Type-tree-is-atom
16862     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:1")  # Type-tree-value
16863     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:2")  # Type-tree-right
16864 $test-function-header-with-multiple-args-and-outputs:inout2:
16865     # inouts = lookup(inouts->next)
16866     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
16867     89/<- %edx 0/r32/eax
16868     # v = lookup(inouts->value)
16869     (lookup *edx *(edx+4))  # List-value List-value => eax
16870     89/<- %ebx 0/r32/eax
16871     # check v->name
16872     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
16873     (check-strings-equal %eax "c" "F - test-function-header-with-multiple-args-and-outputs/inout:2")
16874     # check v->type
16875     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
16876     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:0")  # Type-tree-is-atom
16877     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:1")  # Type-tree-value
16878     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:2")  # Type-tree-right
16879 $test-function-header-with-multiple-args-and-outputs:out0:
16880     # var outputs/edx: (addr list var) = lookup(result->outputs)
16881     (lookup *(ecx+0x10) *(ecx+0x14))  # Function-outputs Function-outputs => eax
16882     89/<- %edx 0/r32/eax
16883     # v = lookup(outputs->value)
16884     (lookup *edx *(edx+4))  # List-value List-value => eax
16885     89/<- %ebx 0/r32/eax
16886     # check v->name
16887     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
16888     (check-strings-equal %eax "_" "F - test-function-header-with-multiple-args-and-outputs/output:0")
16889     # check v->register
16890     (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
16891     (check-strings-equal %eax "ecx" "F - test-function-header-with-multiple-args-and-outputs/output:0/register")
16892     # check v->type
16893     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
16894     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:0")  # Type-tree-is-atom
16895     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:1")  # Type-tree-value
16896     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:2")  # Type-tree-right
16897 $test-function-header-with-multiple-args-and-outputs:out1:
16898     # outputs = lookup(outputs->next)
16899     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
16900     89/<- %edx 0/r32/eax
16901     # v = lookup(inouts->value)
16902     (lookup *edx *(edx+4))  # List-value List-value => eax
16903     89/<- %ebx 0/r32/eax
16904     # check v->name
16905     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
16906     (check-strings-equal %eax "_" "F - test-function-header-with-multiple-args-and-outputs/output:1")
16907     # check v->register
16908     (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
16909     (check-strings-equal %eax "edx" "F - test-function-header-with-multiple-args-and-outputs/output:1/register")
16910     # check v->type
16911     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
16912     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:0")  # Type-tree-is-atom
16913     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:1")  # Type-tree-value
16914     (check-ints-equal *(eax+0c) 0 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:2")  # Type-tree-right
16915     # . epilogue
16916     89/<- %esp 5/r32/ebp
16917     5d/pop-to-ebp
16918     c3/return
16919 
16920 # format for variables with types
16921 #   x: int
16922 #   x: int,
16923 #   x/eax: int
16924 #   x/eax: int,
16925 # ignores at most one trailing comma
16926 # does not support other, non-register metadata
16927 # WARNING: modifies name
16928 parse-var-with-type:  # name: (addr slice), first-line: (addr stream byte), out: (addr handle var), fn-name: (addr array byte), err: (addr buffered-file), ed: (addr exit-descriptor)
16929     # pseudocode:
16930     #   var s: slice
16931     #   if (!slice-ends-with(name, ":"))
16932     #     abort
16933     #   --name->end to skip ':'
16934     #   next-token-from-slice(name->start, name->end, '/', s)
16935     #   new-var-from-slice(s, out)
16936     #   ## register
16937     #   next-token-from-slice(s->end, name->end, '/', s)
16938     #   if (!slice-empty?(s))
16939     #     out->register = slice-to-string(s)
16940     #   ## type
16941     #   var type: (handle type-tree) = parse-type(first-line)
16942     #   out->type = type
16943     #
16944     # . prologue
16945     55/push-ebp
16946     89/<- %ebp 4/r32/esp
16947     # . save registers
16948     50/push-eax
16949     51/push-ecx
16950     52/push-edx
16951     53/push-ebx
16952     56/push-esi
16953     57/push-edi
16954     # esi = name
16955     8b/-> *(ebp+8) 6/r32/esi
16956     # if (!slice-ends-with?(name, ":")) abort
16957     8b/-> *(esi+4) 1/r32/ecx  # Slice-end
16958     49/decrement-ecx
16959     8a/copy-byte *ecx 1/r32/CL
16960     81 4/subop/and %ecx 0xff/imm32
16961     81 7/subop/compare %ecx 0x3a/imm32/colon
16962     0f 85/jump-if-!= $parse-var-with-type:abort/disp32
16963     # --name->end to skip ':'
16964     ff 1/subop/decrement *(esi+4)
16965     # var s/ecx: slice
16966     68/push 0/imm32/end
16967     68/push 0/imm32/start
16968     89/<- %ecx 4/r32/esp
16969 $parse-var-with-type:parse-name:
16970     (next-token-from-slice *esi *(esi+4) 0x2f %ecx)  # Slice-start, Slice-end, '/'
16971 $parse-var-with-type:create-var:
16972     # new-var-from-slice(s, out)
16973     (new-var-from-slice Heap %ecx *(ebp+0x10))
16974     # save out->register
16975 $parse-var-with-type:save-register:
16976     # . var out-addr/edi: (addr var) = lookup(*out)
16977     8b/-> *(ebp+0x10) 7/r32/edi
16978     (lookup *edi *(edi+4))  # => eax
16979     89/<- %edi 0/r32/eax
16980     # . s = next-token(...)
16981     (next-token-from-slice *(ecx+4) *(esi+4) 0x2f %ecx)  # s->end, name->end, '/'
16982     # . if (!slice-empty?(s)) out->register = slice-to-string(s)
16983     {
16984 $parse-var-with-type:write-register:
16985       (slice-empty? %ecx)  # => eax
16986       3d/compare-eax-and 0/imm32/false
16987       75/jump-if-!= break/disp8
16988       # out->register = slice-to-string(s)
16989       8d/copy-address *(edi+0x18) 0/r32/eax  # Var-register
16990       (slice-to-string Heap %ecx %eax)
16991     }
16992 $parse-var-with-type:save-type:
16993     8d/copy-address *(edi+8) 0/r32/eax  # Var-type
16994     (parse-type Heap *(ebp+0xc) %eax *(ebp+0x18) *(ebp+0x1c))
16995 $parse-var-with-type:check-register:
16996     (lookup *(edi+0x18) *(edi+0x1c))  # Var-register Var-register => eax
16997     3d/compare-eax-and 0/imm32
16998     74/jump-if-= $parse-var-with-type:end/disp8
16999     (float-register? %eax)  # => eax
17000     {
17001       3d/compare-eax-and 0/imm32/false
17002       74/jump-if-= break/disp8
17003       # var is in a float register; ensure type is float
17004       (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
17005       (simple-mu-type? %eax 0xf)  # float => eax
17006       3d/compare-eax-and 0/imm32/false
17007       0f 84/jump-if-= $parse-var-with-type:error-non-float-in-floating-point-register/disp32
17008       eb/jump $parse-var-with-type:end/disp8
17009     }
17010     # var is not in a float register; ensure type is not float
17011     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
17012     (simple-mu-type? %eax 0xf)  # float => eax
17013     3d/compare-eax-and 0/imm32/false
17014     0f 85/jump-if-!= $parse-var-with-type:error-float-in-integer-register/disp32
17015 $parse-var-with-type:end:
17016     # . reclaim locals
17017     81 0/subop/add %esp 8/imm32
17018     # . restore registers
17019     5f/pop-to-edi
17020     5e/pop-to-esi
17021     5b/pop-to-ebx
17022     5a/pop-to-edx
17023     59/pop-to-ecx
17024     58/pop-to-eax
17025     # . epilogue
17026     89/<- %esp 5/r32/ebp
17027     5d/pop-to-ebp
17028     c3/return
17029 
17030 $parse-var-with-type:abort:
17031     # error("fn " fn ": var should have form 'name: type' in '" line "'\n")
17032     (write-buffered *(ebp+0x18) "fn ")
17033     (write-buffered *(ebp+0x18) *(ebp+0x14))
17034     (write-buffered *(ebp+0x18) ": var should have form 'name: type' in '")
17035     (flush *(ebp+0x18))
17036     (rewind-stream *(ebp+0xc))
17037     (write-stream-data *(ebp+0x18) *(ebp+0xc))
17038     (write-buffered *(ebp+0x18) "'\n")
17039     (flush *(ebp+0x18))
17040     (stop *(ebp+0x1c) 1)
17041     # never gets here
17042 
17043 $parse-var-with-type:error-float-in-integer-register:
17044     # error("fn " fn ": float var '" var "' should be in a floating-point register\n")
17045     (write-buffered *(ebp+0x18) "fn ")
17046     (write-buffered *(ebp+0x18) *(ebp+0x14))
17047     (write-buffered *(ebp+0x18) ": float var '")
17048     (lookup *edi *(edi+4))  # Var-name Var-name => eax
17049     (write-buffered *(ebp+0x18) %eax)
17050     (write-buffered *(ebp+0x18) "' should be in a floating-point register\n")
17051     (flush *(ebp+0x18))
17052     (stop *(ebp+0x1c) 1)
17053     # never gets here
17054 
17055 $parse-var-with-type:error-non-float-in-floating-point-register:
17056     # error("fn " fn ": non-float var '" var "' should be in an integer register\n")
17057     (write-buffered *(ebp+0x18) "fn ")
17058     (write-buffered *(ebp+0x18) *(ebp+0x14))
17059     (write-buffered *(ebp+0x18) ": non-float var '")
17060     (lookup *edi *(edi+4))  # Var-name Var-name => eax
17061     (write-buffered *(ebp+0x18) %eax)
17062     (write-buffered *(ebp+0x18) "' should be in an integer register\n")
17063     (flush *(ebp+0x18))
17064     (stop *(ebp+0x1c) 1)
17065     # never gets here
17066 
17067 float-register?:  # r: (addr array byte) -> result/eax: boolean
17068     # . prologue
17069     55/push-ebp
17070     89/<- %ebp 4/r32/esp
17071     #
17072     (get Mu-registers-unique *(ebp+8) 0xc "Mu-registers-unique")  # => eax
17073     81 7/subop/compare *eax 8/imm32/start-of-floating-point-registers
17074     0f 9d/set-if->= %al
17075     81 4/subop/and %eax 0xff/imm32
17076 $float-register?:end:
17077     # . epilogue
17078     89/<- %esp 5/r32/ebp
17079     5d/pop-to-ebp
17080     c3/return
17081 
17082 parse-type:  # ad: (addr allocation-descriptor), in: (addr stream byte), out: (addr handle type-tree), err: (addr buffered-file), ed: (addr exit-descriptor)
17083     # pseudocode:
17084     #   var s: slice = next-mu-token(in)
17085     #   assert s != ""
17086     #   assert s != "->"
17087     #   assert s != "{"
17088     #   assert s != "}"
17089     #   if s == ")"
17090     #     return
17091     #   out = allocate(Type-tree)
17092     #   if s != "("
17093     #     HACK: if s is an int, parse and return it
17094     #     out->is-atom? = true
17095     #     if (s[0] == "_")
17096     #       out->value = type-parameter
17097     #       out->parameter-name = slice-to-string(ad, s)
17098     #     else
17099     #       out->value = pos-or-insert-slice(Type-id, s)
17100     #     return
17101     #   out->left = parse-type(ad, in)
17102     #   out->right = parse-type-tree(ad, in)
17103     #
17104     # . prologue
17105     55/push-ebp
17106     89/<- %ebp 4/r32/esp
17107     # . save registers
17108     50/push-eax
17109     51/push-ecx
17110     52/push-edx
17111     # clear out
17112     (zero-out *(ebp+0x10) *Handle-size)
17113     # var s/ecx: slice
17114     68/push 0/imm32
17115     68/push 0/imm32
17116     89/<- %ecx 4/r32/esp
17117     # s = next-mu-token(in)
17118     (next-mu-token *(ebp+0xc) %ecx)
17119 #?     (write-buffered Stderr "tok: ")
17120 #?     (write-slice-buffered Stderr %ecx)
17121 #?     (write-buffered Stderr "$\n")
17122 #?     (flush Stderr)
17123     # assert s != ""
17124     (slice-equal? %ecx "")  # => eax
17125     3d/compare-eax-and 0/imm32/false
17126     0f 85/jump-if-!= $parse-type:abort/disp32
17127     # assert s != "{"
17128     (slice-equal? %ecx "{")  # => eax
17129     3d/compare-eax-and 0/imm32/false
17130     0f 85/jump-if-!= $parse-type:abort/disp32
17131     # assert s != "}"
17132     (slice-equal? %ecx "}")  # => eax
17133     3d/compare-eax-and 0/imm32/false
17134     0f 85/jump-if-!= $parse-type:abort/disp32
17135     # assert s != "->"
17136     (slice-equal? %ecx "->")  # => eax
17137     3d/compare-eax-and 0/imm32/false
17138     0f 85/jump-if-!= $parse-type:abort/disp32
17139     # if (s == ")") return
17140     (slice-equal? %ecx ")")  # => eax
17141     3d/compare-eax-and 0/imm32/false
17142     0f 85/jump-if-!= $parse-type:end/disp32
17143     # out = new tree
17144     (allocate *(ebp+8) *Type-tree-size *(ebp+0x10))
17145     # var out-addr/edx: (addr type-tree) = lookup(*out)
17146     8b/-> *(ebp+0x10) 2/r32/edx
17147     (lookup *edx *(edx+4))  # => eax
17148     89/<- %edx 0/r32/eax
17149     {
17150       # if (s != "(") break
17151       (slice-equal? %ecx "(")  # => eax
17152       3d/compare-eax-and 0/imm32/false
17153       0f 85/jump-if-!= break/disp32
17154       # if s is a number, store it in the type's size field
17155       {
17156 $parse-type:check-for-int:
17157         # var tmp/eax: byte = *s->slice
17158         8b/-> *ecx 0/r32/eax
17159         8a/copy-byte *eax 0/r32/AL
17160         81 4/subop/and %eax 0xff/imm32
17161         # TODO: raise an error on `var x: (array int a)`
17162         (decimal-digit? %eax)  # => eax
17163         3d/compare-eax-and 0/imm32/false
17164         74/jump-if-= break/disp8
17165 $parse-type:int:
17166         # strip out metadata
17167         (next-token-from-slice *ecx *(ecx+4) 0x2f %ecx)
17168         #
17169         (check-mu-hex-int %ecx *(ebp+0x14) *(ebp+0x18))
17170         (parse-hex-int-from-slice %ecx)  # => eax
17171         c7 0/subop/copy *(edx+4) 9/imm32/type-id-array-capacity  # Type-tree-value
17172         89/<- *(edx+8) 0/r32/eax  # Type-tree-value-size
17173         e9/jump $parse-type:end/disp32
17174       }
17175 $parse-type:atom:
17176       # out->is-atom? = true
17177       c7 0/subop/copy *edx 1/imm32/true  # Type-tree-is-atom
17178       {
17179 $parse-type:check-for-type-parameter:
17180         # var tmp/eax: byte = *s->slice
17181         8b/-> *ecx 0/r32/eax
17182         8a/copy-byte *eax 0/r32/AL
17183         81 4/subop/and %eax 0xff/imm32
17184         # if (tmp != '_') break
17185         3d/compare-eax-and 0x5f/imm32/_
17186         75/jump-if-!= break/disp8
17187 $parse-type:type-parameter:
17188         # out->value = type-parameter
17189         c7 0/subop/copy *(edx+4) 0xa/imm32/type-parameter  # Type-tree-value
17190         # out->parameter-name = slice-to-string(ad, s)
17191         8d/copy-address *(edx+8) 0/r32/eax  # Type-tree-parameter-name
17192         (slice-to-string *(ebp+8) %ecx %eax)
17193         e9/jump $parse-type:end/disp32
17194       }
17195 $parse-type:non-type-parameter:
17196       # out->value = pos-or-insert-slice(Type-id, s)
17197       (pos-or-insert-slice Type-id %ecx)  # => eax
17198       89/<- *(edx+4) 0/r32/eax  # Type-tree-value
17199       e9/jump $parse-type:end/disp32
17200     }
17201 $parse-type:non-atom:
17202     # otherwise s == "("
17203     # out->left = parse-type(ad, in)
17204     8d/copy-address *(edx+4) 0/r32/eax  # Type-tree-left
17205     (parse-type *(ebp+8) *(ebp+0xc) %eax *(ebp+0x14) *(ebp+0x18))
17206     # out->right = parse-type-tree(ad, in)
17207     8d/copy-address *(edx+0xc) 0/r32/eax  # Type-tree-right
17208     (parse-type-tree *(ebp+8) *(ebp+0xc) %eax *(ebp+0x14) *(ebp+0x18))
17209 $parse-type:end:
17210     # . reclaim locals
17211     81 0/subop/add %esp 8/imm32
17212     # . restore registers
17213     5a/pop-to-edx
17214     59/pop-to-ecx
17215     58/pop-to-eax
17216     # . epilogue
17217     89/<- %esp 5/r32/ebp
17218     5d/pop-to-ebp
17219     c3/return
17220 
17221 $parse-type:abort:
17222     # error("unexpected token when parsing type: '" s "'\n")
17223     (write-buffered *(ebp+0x14) "unexpected token when parsing type: '")
17224     (write-slice-buffered *(ebp+0x14) %ecx)
17225     (write-buffered *(ebp+0x14) "'\n")
17226     (flush *(ebp+0x14))
17227     (stop *(ebp+0x18) 1)
17228     # never gets here
17229 
17230 parse-type-tree:  # ad: (addr allocation-descriptor), in: (addr stream byte), out: (addr handle type-tree), err: (addr buffered-file), ed: (addr exit-descriptor)
17231     # pseudocode:
17232     #   var tmp: (handle type-tree) = parse-type(ad, in)
17233     #   if tmp == 0
17234     #     return 0
17235     #   out = allocate(Type-tree)
17236     #   out->left = tmp
17237     #   out->right = parse-type-tree(ad, in)
17238     #
17239     # . prologue
17240     55/push-ebp
17241     89/<- %ebp 4/r32/esp
17242     # . save registers
17243     50/push-eax
17244     51/push-ecx
17245     52/push-edx
17246     #
17247     (zero-out *(ebp+0x10) *Handle-size)
17248     # var tmp/ecx: (handle type-tree)
17249     68/push 0/imm32
17250     68/push 0/imm32
17251     89/<- %ecx 4/r32/esp
17252     # tmp = parse-type(ad, in)
17253     (parse-type *(ebp+8) *(ebp+0xc) %ecx *(ebp+0x14) *(ebp+0x18))
17254     # if (tmp == 0) return
17255     81 7/subop/compare *ecx 0/imm32
17256     74/jump-if-= $parse-type-tree:end/disp8
17257     # out = new tree
17258     (allocate *(ebp+8) *Type-tree-size *(ebp+0x10))
17259     # var out-addr/edx: (addr tree) = lookup(*out)
17260     8b/-> *(ebp+0x10) 2/r32/edx
17261     (lookup *edx *(edx+4))  # => eax
17262     89/<- %edx 0/r32/eax
17263     # out->left = tmp
17264     8b/-> *ecx 0/r32/eax
17265     89/<- *(edx+4) 0/r32/eax  # Type-tree-left
17266     8b/-> *(ecx+4) 0/r32/eax
17267     89/<- *(edx+8) 0/r32/eax  # Type-tree-left
17268     # out->right = parse-type-tree(ad, in)
17269     8d/copy-address *(edx+0xc) 0/r32/eax  # Type-tree-right
17270     (parse-type-tree *(ebp+8) *(ebp+0xc) %eax *(ebp+0x14) *(ebp+0x18))
17271 $parse-type-tree:end:
17272     # . reclaim locals
17273     81 0/subop/add %esp 8/imm32
17274     # . restore registers
17275     5a/pop-to-edx
17276     59/pop-to-ecx
17277     58/pop-to-eax
17278     # . epilogue
17279     89/<- %esp 5/r32/ebp
17280     5d/pop-to-ebp
17281     c3/return
17282 
17283 next-mu-token:  # in: (addr stream byte), out: (addr slice)
17284     # pseudocode:
17285     # start:
17286     #   skip-chars-matching-whitespace(in)
17287     #   if in->read >= in->write              # end of in
17288     #     out = {0, 0}
17289     #     return
17290     #   out->start = &in->data[in->read]
17291     #   var curr-byte/eax: byte = in->data[in->read]
17292     #   if curr->byte == ','                  # comment token
17293     #     ++in->read
17294     #     goto start
17295     #   if curr-byte == '#'                   # comment
17296     #     goto done                             # treat as eof
17297     #   if curr-byte == '"'                   # string literal
17298     #     skip-string(in)
17299     #     goto done                           # no metadata
17300     #   if curr-byte == '('
17301     #     ++in->read
17302     #     goto done
17303     #   if curr-byte == ')'
17304     #     ++in->read
17305     #     goto done
17306     #   # read a word
17307     #   while true
17308     #     if in->read >= in->write
17309     #       break
17310     #     curr-byte = in->data[in->read]
17311     #     if curr-byte == ' '
17312     #       break
17313     #     if curr-byte == '\r'
17314     #       break
17315     #     if curr-byte == '\n'
17316     #       break
17317     #     if curr-byte == '('
17318     #       break
17319     #     if curr-byte == ')'
17320     #       break
17321     #     if curr-byte == ','
17322     #       break
17323     #     ++in->read
17324     # done:
17325     #   out->end = &in->data[in->read]
17326     #
17327     # . prologue
17328     55/push-ebp
17329     89/<- %ebp 4/r32/esp
17330     # . save registers
17331     50/push-eax
17332     51/push-ecx
17333     56/push-esi
17334     57/push-edi
17335     # esi = in
17336     8b/-> *(ebp+8) 6/r32/esi
17337     # edi = out
17338     8b/-> *(ebp+0xc) 7/r32/edi
17339 $next-mu-token:start:
17340     (skip-chars-matching-whitespace %esi)
17341 $next-mu-token:check0:
17342     # if (in->read >= in->write) return out = {0, 0}
17343     # . ecx = in->read
17344     8b/-> *(esi+4) 1/r32/ecx
17345     # . if (ecx >= in->write) return out = {0, 0}
17346     3b/compare<- *esi 1/r32/ecx
17347     c7 0/subop/copy *edi 0/imm32
17348     c7 0/subop/copy *(edi+4) 0/imm32
17349     0f 8d/jump-if->= $next-mu-token:end/disp32
17350     # out->start = &in->data[in->read]
17351     8d/copy-address *(esi+ecx+0xc) 0/r32/eax
17352     89/<- *edi 0/r32/eax
17353     # var curr-byte/eax: byte = in->data[in->read]
17354     31/xor-with %eax 0/r32/eax
17355     8a/copy-byte *(esi+ecx+0xc) 0/r32/AL
17356     {
17357 $next-mu-token:check-for-comma:
17358       # if (curr-byte != ',') break
17359       3d/compare-eax-and 0x2c/imm32/comma
17360       75/jump-if-!= break/disp8
17361       # ++in->read
17362       ff 0/subop/increment *(esi+4)
17363       # restart
17364       e9/jump $next-mu-token:start/disp32
17365     }
17366     {
17367 $next-mu-token:check-for-comment:
17368       # if (curr-byte != '#') break
17369       3d/compare-eax-and 0x23/imm32/pound
17370       75/jump-if-!= break/disp8
17371       # return eof
17372       e9/jump $next-mu-token:done/disp32
17373     }
17374     {
17375 $next-mu-token:check-for-string-literal:
17376       # if (curr-byte != '"') break
17377       3d/compare-eax-and 0x22/imm32/dquote
17378       75/jump-if-!= break/disp8
17379       (skip-string %esi)
17380       # return
17381       e9/jump $next-mu-token:done/disp32
17382     }
17383     {
17384 $next-mu-token:check-for-open-paren:
17385       # if (curr-byte != '(') break
17386       3d/compare-eax-and 0x28/imm32/open-paren
17387       75/jump-if-!= break/disp8
17388       # ++in->read
17389       ff 0/subop/increment *(esi+4)
17390       # return
17391       e9/jump $next-mu-token:done/disp32
17392     }
17393     {
17394 $next-mu-token:check-for-close-paren:
17395       # if (curr-byte != ')') break
17396       3d/compare-eax-and 0x29/imm32/close-paren
17397       75/jump-if-!= break/disp8
17398       # ++in->read
17399       ff 0/subop/increment *(esi+4)
17400       # return
17401       e9/jump $next-mu-token:done/disp32
17402     }
17403     {
17404 $next-mu-token:regular-word-without-metadata:
17405       # if (in->read >= in->write) break
17406       # . ecx = in->read
17407       8b/-> *(esi+4) 1/r32/ecx
17408       # . if (ecx >= in->write) break
17409       3b/compare<- *esi 1/r32/ecx
17410       7d/jump-if->= break/disp8
17411       # var c/eax: byte = in->data[in->read]
17412       31/xor-with %eax 0/r32/eax
17413       8a/copy-byte *(esi+ecx+0xc) 0/r32/AL
17414       # if (c == ' ') break
17415       3d/compare-eax-and 0x20/imm32/space
17416       74/jump-if-= break/disp8
17417       # if (c == '\r') break
17418       3d/compare-eax-and 0xd/imm32/carriage-return
17419       74/jump-if-= break/disp8
17420       # if (c == '\n') break
17421       3d/compare-eax-and 0xa/imm32/newline
17422       74/jump-if-= break/disp8
17423       # if (c == '(') break
17424       3d/compare-eax-and 0x28/imm32/open-paren
17425       0f 84/jump-if-= break/disp32
17426       # if (c == ')') break
17427       3d/compare-eax-and 0x29/imm32/close-paren
17428       0f 84/jump-if-= break/disp32
17429       # if (c == ',') break
17430       3d/compare-eax-and 0x2c/imm32/comma
17431       0f 84/jump-if-= break/disp32
17432       # ++in->read
17433       ff 0/subop/increment *(esi+4)
17434       #
17435       e9/jump loop/disp32
17436     }
17437 $next-mu-token:done:
17438     # out->end = &in->data[in->read]
17439     8b/-> *(esi+4) 1/r32/ecx
17440     8d/copy-address *(esi+ecx+0xc) 0/r32/eax
17441     89/<- *(edi+4) 0/r32/eax
17442 $next-mu-token:end:
17443     # . restore registers
17444     5f/pop-to-edi
17445     5e/pop-to-esi
17446     59/pop-to-ecx
17447     58/pop-to-eax
17448     # . epilogue
17449     89/<- %esp 5/r32/ebp
17450     5d/pop-to-ebp
17451     c3/return
17452 
17453 pos-or-insert-slice:  # arr: (addr stream (addr array byte)), s: (addr slice) -> index/eax: int
17454     # . prologue
17455     55/push-ebp
17456     89/<- %ebp 4/r32/esp
17457     # if (pos-slice(arr, s) != -1) return it
17458     (pos-slice *(ebp+8) *(ebp+0xc))  # => eax
17459     3d/compare-eax-and -1/imm32
17460     75/jump-if-!= $pos-or-insert-slice:end/disp8
17461 $pos-or-insert-slice:insert:
17462     # var s2/eax: (handle array byte)
17463     68/push 0/imm32
17464     68/push 0/imm32
17465     89/<- %eax 4/r32/esp
17466     (slice-to-string Heap *(ebp+0xc) %eax)
17467     # throw away alloc-id
17468     (lookup *eax *(eax+4))  # => eax
17469     (write-int *(ebp+8) %eax)
17470     (pos-slice *(ebp+8) *(ebp+0xc))  # => eax
17471 $pos-or-insert-slice:end:
17472     # . reclaim locals
17473     81 0/subop/add %esp 8/imm32
17474     # . epilogue
17475     89/<- %esp 5/r32/ebp
17476     5d/pop-to-ebp
17477     c3/return
17478 
17479 # return the index in an array of strings matching 's', -1 if not found
17480 # index is denominated in elements, not bytes
17481 pos-slice:  # arr: (addr stream (addr array byte)), s: (addr slice) -> index/eax: int
17482     # . prologue
17483     55/push-ebp
17484     89/<- %ebp 4/r32/esp
17485     # . save registers
17486     51/push-ecx
17487     52/push-edx
17488     53/push-ebx
17489     56/push-esi
17490 #?     (write-buffered Stderr "pos-slice: ")
17491 #?     (write-slice-buffered Stderr *(ebp+0xc))
17492 #?     (write-buffered Stderr "\n")
17493 #?     (flush Stderr)
17494     # esi = arr
17495     8b/-> *(ebp+8) 6/r32/esi
17496     # var index/ecx: int = 0
17497     b9/copy-to-ecx 0/imm32
17498     # var curr/edx: (addr (addr array byte)) = arr->data
17499     8d/copy-address *(esi+0xc) 2/r32/edx
17500     # var max/ebx: (addr (addr array byte)) = &arr->data[arr->write]
17501     8b/-> *esi 3/r32/ebx
17502     8d/copy-address *(esi+ebx+0xc) 3/r32/ebx
17503     {
17504 #?       (write-buffered Stderr "  ")
17505 #?       (write-int32-hex-buffered Stderr %ecx)
17506 #?       (write-buffered Stderr "\n")
17507 #?       (flush Stderr)
17508       # if (curr >= max) return -1
17509       39/compare %edx 3/r32/ebx
17510       b8/copy-to-eax -1/imm32
17511       73/jump-if-addr>= $pos-slice:end/disp8
17512       # if (slice-equal?(s, *curr)) break
17513       (slice-equal? *(ebp+0xc) *edx)  # => eax
17514       3d/compare-eax-and 0/imm32/false
17515       75/jump-if-!= break/disp8
17516       # ++index
17517       41/increment-ecx
17518       # curr += 4
17519       81 0/subop/add %edx 4/imm32
17520       #
17521       eb/jump loop/disp8
17522     }
17523     # return index
17524     89/<- %eax 1/r32/ecx
17525 $pos-slice:end:
17526 #?     (write-buffered Stderr "=> ")
17527 #?     (write-int32-hex-buffered Stderr %eax)
17528 #?     (write-buffered Stderr "\n")
17529     # . restore registers
17530     5e/pop-to-esi
17531     5b/pop-to-ebx
17532     5a/pop-to-edx
17533     59/pop-to-ecx
17534     # . epilogue
17535     89/<- %esp 5/r32/ebp
17536     5d/pop-to-ebp
17537     c3/return
17538 
17539 test-parse-var-with-type:
17540     # . prologue
17541     55/push-ebp
17542     89/<- %ebp 4/r32/esp
17543     # setup
17544     8b/-> *Primitive-type-ids 0/r32/eax
17545     89/<- *Type-id 0/r32/eax  # stream-write
17546     # (eax..ecx) = "x:"
17547     b8/copy-to-eax "x:"/imm32
17548     8b/-> *eax 1/r32/ecx
17549     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17550     05/add-to-eax 4/imm32
17551     # var slice/ecx: slice = {eax, ecx}
17552     51/push-ecx
17553     50/push-eax
17554     89/<- %ecx 4/r32/esp
17555     # _test-input-stream contains "int"
17556     (clear-stream _test-input-stream)
17557     (write _test-input-stream "int")
17558     # var v/edx: (handle var)
17559     68/push 0/imm32
17560     68/push 0/imm32
17561     89/<- %edx 4/r32/esp
17562     #
17563     (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0)
17564     # var v-addr/edx: (addr var) = lookup(v)
17565     (lookup *edx *(edx+4))  # => eax
17566     89/<- %edx 0/r32/eax
17567     # check v-addr->name
17568     (lookup *edx *(edx+4))  # Var-name Var-name => eax
17569     (check-strings-equal %eax "x" "F - test-parse-var-with-type/name")
17570     # check v-addr->type
17571     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
17572     (check-ints-equal *eax 1 "F - test-parse-var-with-type/type:0")  # Type-tree-is-atom
17573     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-type/type:1")  # Type-tree-value
17574     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-type/type:2")  # Type-tree-right
17575     # . epilogue
17576     89/<- %esp 5/r32/ebp
17577     5d/pop-to-ebp
17578     c3/return
17579 
17580 test-parse-var-with-type-and-register:
17581     # . prologue
17582     55/push-ebp
17583     89/<- %ebp 4/r32/esp
17584     # setup
17585     8b/-> *Primitive-type-ids 0/r32/eax
17586     89/<- *Type-id 0/r32/eax  # stream-write
17587     # (eax..ecx) = "x/eax:"
17588     b8/copy-to-eax "x/eax:"/imm32
17589     8b/-> *eax 1/r32/ecx
17590     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17591     05/add-to-eax 4/imm32
17592     # var slice/ecx: slice = {eax, ecx}
17593     51/push-ecx
17594     50/push-eax
17595     89/<- %ecx 4/r32/esp
17596     # _test-input-stream contains "int"
17597     (clear-stream _test-input-stream)
17598     (write _test-input-stream "int")
17599     # var v/edx: (handle var)
17600     68/push 0/imm32
17601     68/push 0/imm32
17602     89/<- %edx 4/r32/esp
17603     #
17604     (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0)
17605     # var v-addr/edx: (addr var) = lookup(v)
17606     (lookup *edx *(edx+4))  # => eax
17607     89/<- %edx 0/r32/eax
17608     # check v-addr->name
17609     (lookup *edx *(edx+4))  # Var-name Var-name => eax
17610     (check-strings-equal %eax "x" "F - test-parse-var-with-type-and-register/name")
17611     # check v-addr->register
17612     (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
17613     (check-strings-equal %eax "eax" "F - test-parse-var-with-type-and-register/register")
17614     # check v-addr->type
17615     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
17616     (check-ints-equal *eax 1 "F - test-parse-var-with-type-and-register/type:0")  # Type-tree-is-atom
17617     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-type-and-register/type:1")  # Type-tree-left
17618     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-type-and-register/type:2")  # Type-tree-right
17619     # . epilogue
17620     89/<- %esp 5/r32/ebp
17621     5d/pop-to-ebp
17622     c3/return
17623 
17624 test-parse-var-with-trailing-characters:
17625     # . prologue
17626     55/push-ebp
17627     89/<- %ebp 4/r32/esp
17628     # setup
17629     8b/-> *Primitive-type-ids 0/r32/eax
17630     89/<- *Type-id 0/r32/eax  # stream-write
17631     # (eax..ecx) = "x:"
17632     b8/copy-to-eax "x:"/imm32
17633     8b/-> *eax 1/r32/ecx
17634     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17635     05/add-to-eax 4/imm32
17636     # var slice/ecx: slice = {eax, ecx}
17637     51/push-ecx
17638     50/push-eax
17639     89/<- %ecx 4/r32/esp
17640     # _test-input-stream contains "int,"
17641     (clear-stream _test-input-stream)
17642     (write _test-input-stream "int,")
17643     # var v/edx: (handle var)
17644     68/push 0/imm32
17645     68/push 0/imm32
17646     89/<- %edx 4/r32/esp
17647     #
17648     (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0)
17649     # var v-addr/edx: (addr var) = lookup(v)
17650     (lookup *edx *(edx+4))  # => eax
17651     89/<- %edx 0/r32/eax
17652     # check v-addr->name
17653     (lookup *edx *(edx+4))  # Var-name Var-name => eax
17654     (check-strings-equal %eax "x" "F - test-parse-var-with-trailing-characters/name")
17655     # check v-addr->register
17656     (check-ints-equal *(edx+0x18) 0 "F - test-parse-var-with-trailing-characters/register")  # Var-register
17657     # check v-addr->type
17658     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
17659     (check-ints-equal *eax 1 "F - test-parse-var-with-trailing-characters/type:0")  # Type-tree-is-atom
17660     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-trailing-characters/type:1")  # Type-tree-left
17661     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-trailing-characters/type:1")  # Type-tree-right
17662     # . epilogue
17663     89/<- %esp 5/r32/ebp
17664     5d/pop-to-ebp
17665     c3/return
17666 
17667 test-parse-var-with-register-and-trailing-characters:
17668     # . prologue
17669     55/push-ebp
17670     89/<- %ebp 4/r32/esp
17671     # setup
17672     8b/-> *Primitive-type-ids 0/r32/eax
17673     89/<- *Type-id 0/r32/eax  # stream-write
17674     # (eax..ecx) = "x/eax:"
17675     b8/copy-to-eax "x/eax:"/imm32
17676     8b/-> *eax 1/r32/ecx
17677     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17678     05/add-to-eax 4/imm32
17679     # var slice/ecx: slice = {eax, ecx}
17680     51/push-ecx
17681     50/push-eax
17682     89/<- %ecx 4/r32/esp
17683     # _test-input-stream contains "int,"
17684     (clear-stream _test-input-stream)
17685     (write _test-input-stream "int,")
17686     # var v/edx: (handle var)
17687     68/push 0/imm32
17688     68/push 0/imm32
17689     89/<- %edx 4/r32/esp
17690     #
17691     (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0)
17692     # var v-addr/edx: (addr var) = lookup(v)
17693     (lookup *edx *(edx+4))  # => eax
17694     89/<- %edx 0/r32/eax
17695     # check v-addr->name
17696     (lookup *edx *(edx+4))  # Var-name Var-name => eax
17697     (check-strings-equal %eax "x" "F - test-parse-var-with-register-and-trailing-characters/name")
17698     # check v-addr->register
17699     (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
17700     (check-strings-equal %eax "eax" "F - test-parse-var-with-register-and-trailing-characters/register")
17701     # check v-addr->type
17702     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
17703     (check-ints-equal *eax 1 "F - test-parse-var-with-register-and-trailing-characters/type:0")  # Type-tree-is-atom
17704     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-register-and-trailing-characters/type:1")  # Type-tree-left
17705     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-register-and-trailing-characters/type:2")  # Type-tree-right
17706     # . epilogue
17707     89/<- %esp 5/r32/ebp
17708     5d/pop-to-ebp
17709     c3/return
17710 
17711 test-parse-var-with-compound-type:
17712     # . prologue
17713     55/push-ebp
17714     89/<- %ebp 4/r32/esp
17715     # setup
17716     8b/-> *Primitive-type-ids 0/r32/eax
17717     89/<- *Type-id 0/r32/eax  # stream-write
17718     # (eax..ecx) = "x:"
17719     b8/copy-to-eax "x:"/imm32
17720     8b/-> *eax 1/r32/ecx
17721     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17722     05/add-to-eax 4/imm32
17723     # var slice/ecx: slice = {eax, ecx}
17724     51/push-ecx
17725     50/push-eax
17726     89/<- %ecx 4/r32/esp
17727     # _test-input-stream contains "(addr int)"
17728     (clear-stream _test-input-stream)
17729     (write _test-input-stream "(addr int)")
17730     # var v/edx: (handle var)
17731     68/push 0/imm32
17732     68/push 0/imm32
17733     89/<- %edx 4/r32/esp
17734     #
17735     (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0)
17736     # var v-addr/edx: (addr var) = lookup(v)
17737     (lookup *edx *(edx+4))  # => eax
17738     89/<- %edx 0/r32/eax
17739     # check v-addr->name
17740     (lookup *edx *(edx+4))  # Var-name Var-name => eax
17741     (check-strings-equal %eax "x" "F - test-parse-var-with-compound-type/name")
17742     # check v-addr->register
17743     (check-ints-equal *(edx+0x18) 0 "F - test-parse-var-with-compound-type/register")  # Var-register
17744     # - check v-addr->type
17745     # var type/edx: (addr type-tree) = var->type
17746     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
17747     89/<- %edx 0/r32/eax
17748     # type is a non-atom
17749     (check-ints-equal *edx 0 "F - test-parse-var-with-compound-type/type:0")  # Type-tree-is-atom
17750     # type->left == atom(addr)
17751     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
17752     (check-ints-equal *eax 1 "F - test-parse-var-with-compound-type/type:1")  # Type-tree-is-atom
17753     (check-ints-equal *(eax+4) 2 "F - test-parse-var-with-compound-type/type:2")  # Type-tree-value
17754     # type->right->left == atom(int)
17755     (lookup *(edx+0xc) *(edx+0x10))  # Type-tree-right Type-tree-right => eax
17756     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
17757     (check-ints-equal *eax 1 "F - test-parse-var-with-compound-type/type:3")  # Type-tree-is-atom
17758     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-compound-type/type:4")  # Type-tree-value
17759     # type->right->right == null
17760     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-compound-type/type:5")  # Type-tree-right
17761     # . epilogue
17762     89/<- %esp 5/r32/ebp
17763     5d/pop-to-ebp
17764     c3/return
17765 
17766 # identifier starts with a letter or '$' or '_'
17767 # no constraints at the moment on later letters
17768 # all we really want to do so far is exclude '{', '}' and '->'
17769 identifier?:  # in: (addr slice) -> result/eax: boolean
17770     # . prologue
17771     55/push-ebp
17772     89/<- %ebp 4/r32/esp
17773     # if (slice-empty?(in)) return false
17774     (slice-empty? *(ebp+8))  # => eax
17775     3d/compare-eax-and 0/imm32/false
17776     75/jump-if-!= $identifier?:false/disp8
17777     # var c/eax: byte = *in->start
17778     8b/-> *(ebp+8) 0/r32/eax
17779     8b/-> *eax 0/r32/eax
17780     8a/copy-byte *eax 0/r32/AL
17781     81 4/subop/and %eax 0xff/imm32
17782     # if (c == '$') return true
17783     3d/compare-eax-and 0x24/imm32/$
17784     74/jump-if-= $identifier?:true/disp8
17785     # if (c == '_') return true
17786     3d/compare-eax-and 0x5f/imm32/_
17787     74/jump-if-= $identifier?:true/disp8
17788     # drop case
17789     25/and-eax-with 0x5f/imm32
17790     # if (c < 'A') return false
17791     3d/compare-eax-and 0x41/imm32/A
17792     7c/jump-if-< $identifier?:false/disp8
17793     # if (c > 'Z') return false
17794     3d/compare-eax-and 0x5a/imm32/Z
17795     7f/jump-if-> $identifier?:false/disp8
17796     # otherwise return true
17797 $identifier?:true:
17798     b8/copy-to-eax 1/imm32/true
17799     eb/jump $identifier?:end/disp8
17800 $identifier?:false:
17801     b8/copy-to-eax 0/imm32/false
17802 $identifier?:end:
17803     # . epilogue
17804     89/<- %esp 5/r32/ebp
17805     5d/pop-to-ebp
17806     c3/return
17807 
17808 test-is-identifier-dollar:
17809     # . prologue
17810     55/push-ebp
17811     89/<- %ebp 4/r32/esp
17812     # (eax..ecx) = "$a"
17813     b8/copy-to-eax "$a"/imm32
17814     8b/-> *eax 1/r32/ecx
17815     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17816     05/add-to-eax 4/imm32
17817     # var slice/ecx: slice = {eax, ecx}
17818     51/push-ecx
17819     50/push-eax
17820     89/<- %ecx 4/r32/esp
17821     #
17822     (identifier? %ecx)
17823     (check-ints-equal %eax 1 "F - test-is-identifier-dollar")
17824     # . epilogue
17825     89/<- %esp 5/r32/ebp
17826     5d/pop-to-ebp
17827     c3/return
17828 
17829 test-is-identifier-underscore:
17830     # . prologue
17831     55/push-ebp
17832     89/<- %ebp 4/r32/esp
17833     # (eax..ecx) = "_a"
17834     b8/copy-to-eax "_a"/imm32
17835     8b/-> *eax 1/r32/ecx
17836     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17837     05/add-to-eax 4/imm32
17838     # var slice/ecx: slice = {eax, ecx}
17839     51/push-ecx
17840     50/push-eax
17841     89/<- %ecx 4/r32/esp
17842     #
17843     (identifier? %ecx)
17844     (check-ints-equal %eax 1 "F - test-is-identifier-underscore")
17845     # . epilogue
17846     89/<- %esp 5/r32/ebp
17847     5d/pop-to-ebp
17848     c3/return
17849 
17850 test-is-identifier-a:
17851     # . prologue
17852     55/push-ebp
17853     89/<- %ebp 4/r32/esp
17854     # (eax..ecx) = "a$"
17855     b8/copy-to-eax "a$"/imm32
17856     8b/-> *eax 1/r32/ecx
17857     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17858     05/add-to-eax 4/imm32
17859     # var slice/ecx: slice = {eax, ecx}
17860     51/push-ecx
17861     50/push-eax
17862     89/<- %ecx 4/r32/esp
17863     #
17864     (identifier? %ecx)
17865     (check-ints-equal %eax 1 "F - test-is-identifier-a")
17866     # . epilogue
17867     89/<- %esp 5/r32/ebp
17868     5d/pop-to-ebp
17869     c3/return
17870 
17871 test-is-identifier-z:
17872     # . prologue
17873     55/push-ebp
17874     89/<- %ebp 4/r32/esp
17875     # (eax..ecx) = "z$"
17876     b8/copy-to-eax "z$"/imm32
17877     8b/-> *eax 1/r32/ecx
17878     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17879     05/add-to-eax 4/imm32
17880     # var slice/ecx: slice = {eax, ecx}
17881     51/push-ecx
17882     50/push-eax
17883     89/<- %ecx 4/r32/esp
17884     #
17885     (identifier? %ecx)
17886     (check-ints-equal %eax 1 "F - test-is-identifier-z")
17887     # . epilogue
17888     89/<- %esp 5/r32/ebp
17889     5d/pop-to-ebp
17890     c3/return
17891 
17892 test-is-identifier-A:
17893     # . prologue
17894     55/push-ebp
17895     89/<- %ebp 4/r32/esp
17896     # (eax..ecx) = "A$"
17897     b8/copy-to-eax "A$"/imm32
17898     8b/-> *eax 1/r32/ecx
17899     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17900     05/add-to-eax 4/imm32
17901     # var slice/ecx: slice = {eax, ecx}
17902     51/push-ecx
17903     50/push-eax
17904     89/<- %ecx 4/r32/esp
17905     #
17906     (identifier? %ecx)
17907     (check-ints-equal %eax 1 "F - test-is-identifier-A")
17908     # . epilogue
17909     89/<- %esp 5/r32/ebp
17910     5d/pop-to-ebp
17911     c3/return
17912 
17913 test-is-identifier-Z:
17914     # . prologue
17915     55/push-ebp
17916     89/<- %ebp 4/r32/esp
17917     # (eax..ecx) = "Z$"
17918     b8/copy-to-eax "Z$"/imm32
17919     8b/-> *eax 1/r32/ecx
17920     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17921     05/add-to-eax 4/imm32
17922     # var slice/ecx: slice = {eax, ecx}
17923     51/push-ecx
17924     50/push-eax
17925     89/<- %ecx 4/r32/esp
17926     #
17927     (identifier? %ecx)
17928     (check-ints-equal %eax 1 "F - test-is-identifier-Z")
17929     # . epilogue
17930     89/<- %esp 5/r32/ebp
17931     5d/pop-to-ebp
17932     c3/return
17933 
17934 test-is-identifier-at:
17935     # character before 'A' is invalid
17936     # . prologue
17937     55/push-ebp
17938     89/<- %ebp 4/r32/esp
17939     # (eax..ecx) = "@a"
17940     b8/copy-to-eax "@a"/imm32
17941     8b/-> *eax 1/r32/ecx
17942     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17943     05/add-to-eax 4/imm32
17944     # var slice/ecx: slice = {eax, ecx}
17945     51/push-ecx
17946     50/push-eax
17947     89/<- %ecx 4/r32/esp
17948     #
17949     (identifier? %ecx)
17950     (check-ints-equal %eax 0 "F - test-is-identifier-@")
17951     # . epilogue
17952     89/<- %esp 5/r32/ebp
17953     5d/pop-to-ebp
17954     c3/return
17955 
17956 test-is-identifier-square-bracket:
17957     # character after 'Z' is invalid
17958     # . prologue
17959     55/push-ebp
17960     89/<- %ebp 4/r32/esp
17961     # (eax..ecx) = "[a"
17962     b8/copy-to-eax "[a"/imm32
17963     8b/-> *eax 1/r32/ecx
17964     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17965     05/add-to-eax 4/imm32
17966     # var slice/ecx: slice = {eax, ecx}
17967     51/push-ecx
17968     50/push-eax
17969     89/<- %ecx 4/r32/esp
17970     #
17971     (identifier? %ecx)
17972     (check-ints-equal %eax 0 "F - test-is-identifier-@")
17973     # . epilogue
17974     89/<- %esp 5/r32/ebp
17975     5d/pop-to-ebp
17976     c3/return
17977 
17978 test-is-identifier-backtick:
17979     # character before 'a' is invalid
17980     # . prologue
17981     55/push-ebp
17982     89/<- %ebp 4/r32/esp
17983     # (eax..ecx) = "`a"
17984     b8/copy-to-eax "`a"/imm32
17985     8b/-> *eax 1/r32/ecx
17986     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17987     05/add-to-eax 4/imm32
17988     # var slice/ecx: slice = {eax, ecx}
17989     51/push-ecx
17990     50/push-eax
17991     89/<- %ecx 4/r32/esp
17992     #
17993     (identifier? %ecx)
17994     (check-ints-equal %eax 0 "F - test-is-identifier-backtick")
17995     # . epilogue
17996     89/<- %esp 5/r32/ebp
17997     5d/pop-to-ebp
17998     c3/return
17999 
18000 test-is-identifier-curly-brace-open:
18001     # character after 'z' is invalid; also used for blocks
18002     # . prologue
18003     55/push-ebp
18004     89/<- %ebp 4/r32/esp
18005     # (eax..ecx) = "{a"
18006     b8/copy-to-eax "{a"/imm32
18007     8b/-> *eax 1/r32/ecx
18008     8d/copy-address *(eax+ecx+4) 1/r32/ecx
18009     05/add-to-eax 4/imm32
18010     # var slice/ecx: slice = {eax, ecx}
18011     51/push-ecx
18012     50/push-eax
18013     89/<- %ecx 4/r32/esp
18014     #
18015     (identifier? %ecx)
18016     (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-open")
18017     # . epilogue
18018     89/<- %esp 5/r32/ebp
18019     5d/pop-to-ebp
18020     c3/return
18021 
18022 test-is-identifier-curly-brace-close:
18023     # . prologue
18024     55/push-ebp
18025     89/<- %ebp 4/r32/esp
18026     # (eax..ecx) = "}a"
18027     b8/copy-to-eax "}a"/imm32
18028     8b/-> *eax 1/r32/ecx
18029     8d/copy-address *(eax+ecx+4) 1/r32/ecx
18030     05/add-to-eax 4/imm32
18031     # var slice/ecx: slice = {eax, ecx}
18032     51/push-ecx
18033     50/push-eax
18034     89/<- %ecx 4/r32/esp
18035     #
18036     (identifier? %ecx)
18037     (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-close")
18038     # . epilogue
18039     89/<- %esp 5/r32/ebp
18040     5d/pop-to-ebp
18041     c3/return
18042 
18043 test-is-identifier-hyphen:
18044     # disallow leading '-' since '->' has special meaning
18045     # . prologue
18046     55/push-ebp
18047     89/<- %ebp 4/r32/esp
18048     # (eax..ecx) = "-a"
18049     b8/copy-to-eax "-a"/imm32
18050     8b/-> *eax 1/r32/ecx
18051     8d/copy-address *(eax+ecx+4) 1/r32/ecx
18052     05/add-to-eax 4/imm32
18053     # var slice/ecx: slice = {eax, ecx}
18054     51/push-ecx
18055     50/push-eax
18056     89/<- %ecx 4/r32/esp
18057     #
18058     (identifier? %ecx)
18059     (check-ints-equal %eax 0 "F - test-is-identifier-hyphen")
18060     # . epilogue
18061     89/<- %esp 5/r32/ebp
18062     5d/pop-to-ebp
18063     c3/return
18064 
18065 populate-mu-function-body:  # in: (addr buffered-file), out: (addr function), vars: (addr stack live-var), err: (addr buffered-file), ed: (addr exit-descriptor)
18066     # . prologue
18067     55/push-ebp
18068     89/<- %ebp 4/r32/esp
18069     # . save registers
18070     50/push-eax
18071     56/push-esi
18072     57/push-edi
18073     # esi = in
18074     8b/-> *(ebp+8) 6/r32/esi
18075     # edi = out
18076     8b/-> *(ebp+0xc) 7/r32/edi
18077     # initialize some global state
18078     c7 0/subop/copy *Curr-block-depth 1/imm32
18079     # parse-mu-block(in, vars, out, out->body)
18080     8d/copy-address *(edi+0x18) 0/r32/eax  # Function-body
18081     (parse-mu-block %esi *(ebp+0x10) %edi %eax *(ebp+0x14) *(ebp+0x18))
18082 $populate-mu-function-body:end:
18083     # . restore registers
18084     5f/pop-to-edi
18085     5e/pop-to-esi
18086     58/pop-to-eax
18087     # . epilogue
18088     89/<- %esp 5/r32/ebp
18089     5d/pop-to-ebp
18090     c3/return
18091 
18092 # parses a block, assuming that the leading '{' has already been read by the caller
18093 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)
18094     # pseudocode:
18095     #   var line: (stream byte 512)
18096     #   var word-slice: slice
18097     #   allocate(Heap, Stmt-size, out)
18098     #   var out-addr: (addr block) = lookup(*out)
18099     #   out-addr->tag = 0/block
18100     #   out-addr->var = some unique name
18101     #   push(vars, {out-addr->var, false})
18102     #   while true                                  # line loop
18103     #     clear-stream(line)
18104     #     read-line-buffered(in, line)
18105     #     if (line->write == 0) break               # end of file
18106     #     word-slice = next-mu-token(line)
18107     #     if slice-empty?(word-slice)               # end of line
18108     #       continue
18109     #     else if slice-starts-with?(word-slice, "#")
18110     #       continue
18111     #     else if slice-equal?(word-slice, "{")
18112     #       assert(no-tokens-in(line))
18113     #       block = parse-mu-block(in, vars, fn)
18114     #       append-to-block(out-addr, block)
18115     #     else if slice-equal?(word-slice, "}")
18116     #       break
18117     #     else if slice-ends-with?(word-slice, ":")
18118     #       # TODO: error-check the rest of 'line'
18119     #       --word-slice->end to skip ':'
18120     #       named-block = parse-mu-named-block(word-slice, in, vars, fn)
18121     #       append-to-block(out-addr, named-block)
18122     #     else if slice-equal?(word-slice, "var")
18123     #       var-def = parse-mu-var-def(line, vars, fn)
18124     #       append-to-block(out-addr, var-def)
18125     #     else
18126     #       stmt = parse-mu-stmt(line, vars, fn)
18127     #       append-to-block(out-addr, stmt)
18128     #   pop(vars)
18129     #
18130     # . prologue
18131     55/push-ebp
18132     89/<- %ebp 4/r32/esp
18133     # . save registers
18134     50/push-eax
18135     51/push-ecx
18136     52/push-edx
18137     53/push-ebx
18138     57/push-edi
18139     # var line/ecx: (stream byte 512)
18140     81 5/subop/subtract %esp 0x200/imm32
18141     68/push 0x200/imm32/size
18142     68/push 0/imm32/read
18143     68/push 0/imm32/write
18144     89/<- %ecx 4/r32/esp
18145     # var word-slice/edx: slice
18146     68/push 0/imm32/end
18147     68/push 0/imm32/start
18148     89/<- %edx 4/r32/esp
18149     # allocate into out
18150     (allocate Heap *Stmt-size *(ebp+0x14))
18151     # var out-addr/edi: (addr block) = lookup(*out)
18152     8b/-> *(ebp+0x14) 7/r32/edi
18153     (lookup *edi *(edi+4))  # => eax
18154     89/<- %edi 0/r32/eax
18155     # out-addr->tag is 0 (block) by default
18156     # set out-addr->var
18157     8d/copy-address *(edi+0xc) 0/r32/eax  # Block-var
18158     (new-block-name *(ebp+0x10) %eax)
18159     # push(vars, out-addr->var)
18160     (push *(ebp+0xc) *(edi+0xc))  # Block-var
18161     (push *(ebp+0xc) *(edi+0x10))  # Block-var
18162     (push *(ebp+0xc) 0)  # false
18163     # increment *Curr-block-depth
18164     ff 0/subop/increment *Curr-block-depth
18165     {
18166 $parse-mu-block:line-loop:
18167       # line = read-line-buffered(in)
18168       (clear-stream %ecx)
18169       (read-line-buffered *(ebp+8) %ecx)
18170 #?       (write-buffered Stderr "line: ")
18171 #?       (write-stream-data Stderr %ecx)
18172 #? #?       (write-buffered Stderr Newline)  # line has its own newline
18173 #?       (flush Stderr)
18174 #?       (rewind-stream %ecx)
18175       # if (line->write == 0) break
18176       81 7/subop/compare *ecx 0/imm32
18177       0f 84/jump-if-= break/disp32
18178 #?       (write-buffered Stderr "vars:\n")
18179 #?       (dump-vars *(ebp+0xc))
18180       # word-slice = next-mu-token(line)
18181       (next-mu-token %ecx %edx)
18182 #?       (write-buffered Stderr "word: ")
18183 #?       (write-slice-buffered Stderr %edx)
18184 #?       (write-buffered Stderr Newline)
18185 #?       (flush Stderr)
18186       # if slice-empty?(word-slice) continue
18187       (slice-empty? %edx)
18188       3d/compare-eax-and 0/imm32/false
18189       0f 85/jump-if-!= loop/disp32
18190       # if (slice-starts-with?(word-slice, '#') continue
18191       # . eax = *word-slice->start
18192       8b/-> *edx 0/r32/eax
18193       8a/copy-byte *eax 0/r32/AL
18194       81 4/subop/and %eax 0xff/imm32
18195       # . if (eax == '#') continue
18196       3d/compare-eax-and 0x23/imm32/hash
18197       0f 84/jump-if-= loop/disp32
18198       # if slice-equal?(word-slice, "{")
18199       {
18200 $parse-mu-block:check-for-block:
18201         (slice-equal? %edx "{")
18202         3d/compare-eax-and 0/imm32/false
18203         74/jump-if-= break/disp8
18204         (check-no-tokens-left %ecx)
18205         # parse new block and append
18206         # . var tmp/eax: (handle block)
18207         68/push 0/imm32
18208         68/push 0/imm32
18209         89/<- %eax 4/r32/esp
18210         # .
18211         (parse-mu-block *(ebp+8) *(ebp+0xc) *(ebp+0x10) %eax *(ebp+0x18) *(ebp+0x1c))
18212         (append-to-block Heap %edi  *eax *(eax+4))
18213         # . reclaim tmp
18214         81 0/subop/add %esp 8/imm32
18215         # .
18216         e9/jump $parse-mu-block:line-loop/disp32
18217       }
18218       # if slice-equal?(word-slice, "}") break
18219 $parse-mu-block:check-for-end:
18220       (slice-equal? %edx "}")
18221       3d/compare-eax-and 0/imm32/false
18222       0f 85/jump-if-!= break/disp32
18223       # if slice-ends-with?(word-slice, ":") parse named block and append
18224       {
18225 $parse-mu-block:check-for-named-block:
18226         # . eax = *(word-slice->end-1)
18227         8b/-> *(edx+4) 0/r32/eax
18228         48/decrement-eax
18229         8a/copy-byte *eax 0/r32/AL
18230         81 4/subop/and %eax 0xff/imm32
18231         # . if (eax != ':') break
18232         3d/compare-eax-and 0x3a/imm32/colon
18233         0f 85/jump-if-!= break/disp32
18234         # TODO: error-check the rest of 'line'
18235         #
18236         # skip ':'
18237         ff 1/subop/decrement *(edx+4)  # Slice-end
18238         # var tmp/eax: (handle block)
18239         68/push 0/imm32
18240         68/push 0/imm32
18241         89/<- %eax 4/r32/esp
18242         #
18243         (parse-mu-named-block %edx *(ebp+8) *(ebp+0xc) *(ebp+0x10) %eax *(ebp+0x18) *(ebp+0x1c))
18244         (append-to-block Heap %edi  *eax *(eax+4))
18245         # reclaim tmp
18246         81 0/subop/add %esp 8/imm32
18247         #
18248         e9/jump $parse-mu-block:line-loop/disp32
18249       }
18250       # if slice-equal?(word-slice, "var")
18251       {
18252 $parse-mu-block:check-for-var:
18253         (slice-equal? %edx "var")
18254         3d/compare-eax-and 0/imm32/false
18255         74/jump-if-= break/disp8
18256         # var tmp/eax: (handle block)
18257         68/push 0/imm32
18258         68/push 0/imm32
18259         89/<- %eax 4/r32/esp
18260         #
18261         (parse-mu-var-def %ecx *(ebp+0xc) %eax *(ebp+0x10) *(ebp+0x18) *(ebp+0x1c))
18262         (append-to-block Heap %edi  *eax *(eax+4))
18263         # reclaim tmp
18264         81 0/subop/add %esp 8/imm32
18265         #
18266         e9/jump $parse-mu-block:line-loop/disp32
18267       }
18268 $parse-mu-block:regular-stmt:
18269       # otherwise
18270       # var tmp/eax: (handle block)
18271       68/push 0/imm32
18272       68/push 0/imm32
18273       89/<- %eax 4/r32/esp
18274       #
18275       (parse-mu-stmt %ecx *(ebp+0xc) *(ebp+0x10) %eax *(ebp+0x18) *(ebp+0x1c))
18276       (append-to-block Heap %edi  *eax *(eax+4))
18277       # reclaim tmp
18278       81 0/subop/add %esp 8/imm32
18279       #
18280       e9/jump loop/disp32
18281     } # end line loop
18282     (clean-up-blocks *(ebp+0xc) *Curr-block-depth *(ebp+0x10))
18283     # decrement *Curr-block-depth
18284     ff 1/subop/decrement *Curr-block-depth
18285     # pop(vars)
18286     (pop *(ebp+0xc))  # => eax
18287     (pop *(ebp+0xc))  # => eax
18288     (pop *(ebp+0xc))  # => eax
18289 $parse-mu-block:end:
18290     # . reclaim locals
18291     81 0/subop/add %esp 0x214/imm32
18292     # . restore registers
18293     5f/pop-to-edi
18294     5b/pop-to-ebx
18295     5a/pop-to-edx
18296     59/pop-to-ecx
18297     58/pop-to-eax
18298     # . epilogue
18299     89/<- %esp 5/r32/ebp
18300     5d/pop-to-ebp
18301     c3/return
18302 
18303 $parse-mu-block:abort:
18304     # error("'{' or '}' should be on its own line, but got '")
18305     (write-buffered *(ebp+0x18) "'{' or '}' should be on its own line, but got '")
18306     (rewind-stream %ecx)
18307     (write-stream-data *(ebp+0x18) %ecx)
18308     (write-buffered *(ebp+0x18) "'\n")
18309     (flush *(ebp+0x18))
18310     (stop *(ebp+0x1c) 1)
18311     # never gets here
18312 
18313 new-block-name:  # fn: (addr function), out: (addr handle var)
18314     # . prologue
18315     55/push-ebp
18316     89/<- %ebp 4/r32/esp
18317     # . save registers
18318     50/push-eax
18319     51/push-ecx
18320     52/push-edx
18321     # var n/ecx: int = len(fn->name) + 10 for an int + 2 for '$:'
18322     8b/-> *(ebp+8) 0/r32/eax
18323     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18324     8b/-> *eax 0/r32/eax  # String-size
18325     05/add-to-eax 0xd/imm32  # 10 + 2 for '$:'
18326     89/<- %ecx 0/r32/eax
18327     # var name/edx: (stream byte n)
18328     29/subtract-from %esp 1/r32/ecx
18329     ff 6/subop/push %ecx
18330     68/push 0/imm32/read
18331     68/push 0/imm32/write
18332     89/<- %edx 4/r32/esp
18333     (clear-stream %edx)
18334     # eax = fn->name
18335     8b/-> *(ebp+8) 0/r32/eax
18336     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18337     # construct result using Next-block-index (and increment it)
18338     (write %edx "$")
18339     (write %edx %eax)
18340     (write %edx ":")
18341     (write-int32-hex %edx *Next-block-index)
18342     ff 0/subop/increment *Next-block-index
18343     # var s/eax: slice = {name->data, name->data + name->write}  (clobbering edx)
18344     # . eax = name->write
18345     8b/-> *edx 0/r32/eax
18346     # . edx = name->data
18347     8d/copy-address *(edx+0xc) 2/r32/edx
18348     # . eax = name->write + name->data
18349     01/add-to %eax 2/r32/edx
18350     # . push {edx, eax}
18351     ff 6/subop/push %eax
18352     ff 6/subop/push %edx
18353     89/<- %eax 4/r32/esp
18354     # out = new literal(s)
18355     (new-literal Heap %eax *(ebp+0xc))
18356 #?     8b/-> *(ebp+0xc) 0/r32/eax
18357 #?     (write-buffered Stderr "type allocid in caller after new-literal: ")
18358 #?     (write-int32-hex-buffered Stderr *(eax+8))
18359 #?     (write-buffered Stderr " for var ")
18360 #?     (write-int32-hex-buffered Stderr %eax)
18361 #?     (write-buffered Stderr Newline)
18362 #?     (flush Stderr)
18363 $new-block-name:end:
18364     # . reclaim locals
18365     81 0/subop/add %ecx 0xc/imm32  # name.{read/write/len}
18366     81 0/subop/add %ecx 8/imm32  # slice
18367     01/add-to %esp 1/r32/ecx
18368     # . restore registers
18369     5a/pop-to-edx
18370     59/pop-to-ecx
18371     58/pop-to-eax
18372     # . epilogue
18373     89/<- %esp 5/r32/ebp
18374     5d/pop-to-ebp
18375     c3/return
18376 
18377 check-no-tokens-left:  # line: (addr stream byte)
18378     # . prologue
18379     55/push-ebp
18380     89/<- %ebp 4/r32/esp
18381     # . save registers
18382     50/push-eax
18383     51/push-ecx
18384     # var s/ecx: slice
18385     68/push 0/imm32/end
18386     68/push 0/imm32/start
18387     89/<- %ecx 4/r32/esp
18388     #
18389     (next-mu-token *(ebp+8) %ecx)
18390     # if slice-empty?(s) return
18391     (slice-empty? %ecx)
18392     3d/compare-eax-and 0/imm32/false
18393     75/jump-if-!= $check-no-tokens-left:end/disp8
18394     # if (slice-starts-with?(s, '#') return
18395     # . eax = *s->start
18396     8b/-> *edx 0/r32/eax
18397     8a/copy-byte *eax 0/r32/AL
18398     81 4/subop/and %eax 0xff/imm32
18399     # . if (eax == '#') continue
18400     3d/compare-eax-and 0x23/imm32/hash
18401     74/jump-if-= $check-no-tokens-left:end/disp8
18402     # abort
18403     (write-buffered Stderr "'{' or '}' should be on its own line, but got '")
18404     (rewind-stream %ecx)
18405     (write-stream 2 %ecx)
18406     (write-buffered Stderr "'\n")
18407     (flush Stderr)
18408     # . syscall(exit, 1)
18409     bb/copy-to-ebx  1/imm32
18410     e8/call syscall_exit/disp32
18411     # never gets here
18412 $check-no-tokens-left:end:
18413     # . reclaim locals
18414     81 0/subop/add %esp 8/imm32
18415     # . restore registers
18416     59/pop-to-ecx
18417     58/pop-to-eax
18418     # . epilogue
18419     89/<- %esp 5/r32/ebp
18420     5d/pop-to-ebp
18421     c3/return
18422 
18423 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)
18424     # pseudocode:
18425     #   var v: (handle var)
18426     #   new-literal(name, v)
18427     #   push(vars, {v, false})
18428     #   parse-mu-block(in, vars, fn, out)
18429     #   pop(vars)
18430     #   out->tag = block
18431     #   out->var = v
18432     #
18433     # . prologue
18434     55/push-ebp
18435     89/<- %ebp 4/r32/esp
18436     # . save registers
18437     50/push-eax
18438     51/push-ecx
18439     57/push-edi
18440     # var v/ecx: (handle var)
18441     68/push 0/imm32
18442     68/push 0/imm32
18443     89/<- %ecx 4/r32/esp
18444     #
18445     (new-literal Heap *(ebp+8) %ecx)
18446     # push(vars, v)
18447     (push *(ebp+0x10) *ecx)
18448     (push *(ebp+0x10) *(ecx+4))
18449     (push *(ebp+0x10) 0)  # false
18450     #
18451     (parse-mu-block *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c) *(ebp+0x20))
18452     # pop v off vars
18453     (pop *(ebp+0x10))  # => eax
18454     (pop *(ebp+0x10))  # => eax
18455     (pop *(ebp+0x10))  # => eax
18456     # var out-addr/edi: (addr stmt) = lookup(*out)
18457     8b/-> *(ebp+0x18) 7/r32/edi
18458     (lookup *edi *(edi+4))  # => eax
18459     89/<- %edi 0/r32/eax
18460     # out-addr->tag = named-block
18461     c7 0/subop/copy *edi 0/imm32/block  # Stmt-tag
18462     # out-addr->var = v
18463     8b/-> *ecx 0/r32/eax
18464     89/<- *(edi+0xc) 0/r32/eax  # Block-var
18465     8b/-> *(ecx+4) 0/r32/eax
18466     89/<- *(edi+0x10) 0/r32/eax  # Block-var
18467 $parse-mu-named-block:end:
18468     # . reclaim locals
18469     81 0/subop/add %esp 8/imm32
18470     # . restore registers
18471     5f/pop-to-edi
18472     59/pop-to-ecx
18473     58/pop-to-eax
18474     # . epilogue
18475     89/<- %esp 5/r32/ebp
18476     5d/pop-to-ebp
18477     c3/return
18478 
18479 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)
18480     # . prologue
18481     55/push-ebp
18482     89/<- %ebp 4/r32/esp
18483     # . save registers
18484     50/push-eax
18485     51/push-ecx
18486     52/push-edx
18487     56/push-esi
18488     57/push-edi
18489     # edi = out
18490     8b/-> *(ebp+0x10) 7/r32/edi
18491     # var word-slice/ecx: slice
18492     68/push 0/imm32/end
18493     68/push 0/imm32/start
18494     89/<- %ecx 4/r32/esp
18495     # var v/edx: (handle var)
18496     68/push 0/imm32
18497     68/push 0/imm32
18498     89/<- %edx 4/r32/esp
18499     # v = parse-var-with-type(next-mu-token(line))
18500     (next-mu-token *(ebp+8) %ecx)
18501     {
18502       # just for tests, support null fn
18503       8b/-> *(ebp+0x14) 0/r32/eax
18504       3d/compare-eax-and 0/imm32
18505       74/jump-if-= break/disp8
18506       (lookup *eax *(eax+4))  # Var-name Var-name => eax
18507     }
18508     (parse-var-with-type %ecx *(ebp+8) %edx %eax *(ebp+0x18) *(ebp+0x1c))
18509     # var v-addr/esi: (addr var)
18510     (lookup *edx *(edx+4))  # => eax
18511     89/<- %esi 0/r32/eax
18512     # v->block-depth = *Curr-block-depth
18513     8b/-> *Curr-block-depth 0/r32/eax
18514     89/<- *(esi+0x10) 0/r32/eax  # Var-block-depth
18515     # either v has no register and there's no more to this line
18516     81 7/subop/compare *(esi+0x18) 0/imm32
18517     {
18518       75/jump-if-!= break/disp8
18519       # if v-addr->type == byte, abort
18520       (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
18521       (simple-mu-type? %eax 8)  # byte => eax
18522       3d/compare-eax-and 0/imm32/false
18523       0f 85/jump-if-!= $parse-mu-var-def:error-byte-on-stack/disp32
18524       # ensure that there's nothing else on this line
18525       (next-mu-token *(ebp+8) %ecx)
18526       (slice-empty? %ecx)  # => eax
18527       3d/compare-eax-and 0/imm32/false
18528       0f 84/jump-if-= $parse-mu-var-def:error2/disp32
18529       #
18530       (new-var-def Heap  *edx *(edx+4)  %edi)
18531       e9/jump $parse-mu-var-def:update-vars/disp32
18532     }
18533     # or v has a register and there's more to this line
18534     {
18535       0f 84/jump-if-= break/disp32
18536       # if v-addr->type == byte, check for unsupported registers
18537       {
18538         (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
18539         (simple-mu-type? %eax 8)  # byte => eax
18540         3d/compare-eax-and 0/imm32/false
18541         74/jump-if-= break/disp8
18542         (lookup *(esi+0x18) *(esi+0x1c))  # => eax
18543         (string-equal? %eax "esi")  # => eax
18544         3d/compare-eax-and 0/imm32/false
18545         0f 85/jump-if-!= $parse-mu-var-def:error-byte-registers/disp32
18546         (lookup *(esi+0x18) *(esi+0x1c))  # => eax
18547         (string-equal? %eax "edi")  # => eax
18548         3d/compare-eax-and 0/imm32/false
18549         0f 85/jump-if-!= $parse-mu-var-def:error-byte-registers/disp32
18550       }
18551       # TODO: vars of type 'byte' should only be initialized by clearing to 0
18552       # ensure that the next word is '<-'
18553       (next-mu-token *(ebp+8) %ecx)
18554       (slice-equal? %ecx "<-")  # => eax
18555       3d/compare-eax-and 0/imm32/false
18556       0f 84/jump-if-= $parse-mu-var-def:error1/disp32
18557       #
18558       (new-reg-var-def Heap  *edx *(edx+4)  %edi)
18559       (lookup *edi *(edi+4))  # => eax
18560       (add-operation-and-inputs-to-stmt %eax *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
18561     }
18562 $parse-mu-var-def:update-vars:
18563     # push 'v' at end of function
18564     (push *(ebp+0xc) *edx)
18565     (push *(ebp+0xc) *(edx+4))
18566     (push *(ebp+0xc) 0)  # Live-var-register-spilled is unused during parsing
18567 $parse-mu-var-def:end:
18568     # . reclaim locals
18569     81 0/subop/add %esp 0x10/imm32
18570     # . restore registers
18571     5f/pop-to-edi
18572     5e/pop-to-esi
18573     5a/pop-to-edx
18574     59/pop-to-ecx
18575     58/pop-to-eax
18576     # . epilogue
18577     89/<- %esp 5/r32/ebp
18578     5d/pop-to-ebp
18579     c3/return
18580 
18581 $parse-mu-var-def:error1:
18582     (rewind-stream *(ebp+8))
18583     # error("register variable requires a valid instruction to initialize but got '" line "'\n")
18584     (write-buffered *(ebp+0x18) "register variable requires a valid instruction to initialize but got '")
18585     (flush *(ebp+0x18))
18586     (write-stream-data *(ebp+0x18) *(ebp+8))
18587     (write-buffered *(ebp+0x18) "'\n")
18588     (flush *(ebp+0x18))
18589     (stop *(ebp+0x1c) 1)
18590     # never gets here
18591 
18592 $parse-mu-var-def:error2:
18593     # error("fn " fn ": var " var ": variables on the stack can't take an initializer\n")
18594     (write-buffered *(ebp+0x18) "fn ")
18595     8b/-> *(ebp+0x14) 0/r32/eax
18596     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18597     (write-buffered *(ebp+0x18) %eax)
18598     (write-buffered *(ebp+0x18) ": var ")
18599     # var v-addr/eax: (addr var) = lookup(v)
18600     (lookup *edx *(edx+4))  # => eax
18601     (lookup *eax *(eax+4))  # Var-name Var-name => eax
18602     (write-buffered *(ebp+0x18) %eax)
18603     (write-buffered *(ebp+0x18) ": variables on the stack can't take an initializer\n")
18604     (flush *(ebp+0x18))
18605     (stop *(ebp+0x1c) 1)
18606     # never gets here
18607 
18608 $parse-mu-var-def:error-byte-on-stack:
18609     # error("fn " fn ": var '" var "' of type 'byte' cannot be on the stack\n")
18610     (write-buffered *(ebp+0x18) "fn ")
18611     8b/-> *(ebp+0x14) 0/r32/eax
18612     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18613     (write-buffered *(ebp+0x18) %eax)
18614     (write-buffered *(ebp+0x18) ": var '")
18615     # var v-addr/eax: (addr var) = lookup(v)
18616     (lookup *edx *(edx+4))  # => eax
18617     (lookup *eax *(eax+4))  # Var-name Var-name => eax
18618     (write-buffered *(ebp+0x18) %eax)
18619     (write-buffered *(ebp+0x18) "' of type 'byte' cannot be on the stack\n")
18620     (flush *(ebp+0x18))
18621     (stop *(ebp+0x1c) 1)
18622     # never gets here
18623 
18624 $parse-mu-var-def:error-byte-registers:
18625     # error("fn " fn ": var '" var "' of type 'byte' cannot be in esi or edi\n")
18626     (write-buffered *(ebp+0x18) "fn ")
18627     8b/-> *(ebp+0x14) 0/r32/eax
18628     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18629     (write-buffered *(ebp+0x18) %eax)
18630     (write-buffered *(ebp+0x18) ": var '")
18631     # var v-addr/eax: (addr var) = lookup(v)
18632     (lookup *edx *(edx+4))  # => eax
18633     (lookup *eax *(eax+4))  # Var-name Var-name => eax
18634     (write-buffered *(ebp+0x18) %eax)
18635     (write-buffered *(ebp+0x18) "' of type 'byte' cannot be in esi or edi\n")
18636     (flush *(ebp+0x18))
18637     (stop *(ebp+0x1c) 1)
18638     # never gets here
18639 
18640 test-parse-mu-var-def:
18641     # 'var n: int'
18642     # . prologue
18643     55/push-ebp
18644     89/<- %ebp 4/r32/esp
18645     # setup
18646     8b/-> *Primitive-type-ids 0/r32/eax
18647     89/<- *Type-id 0/r32/eax  # stream-write
18648     (clear-stream _test-input-stream)
18649     (write _test-input-stream "n: int\n")  # caller has consumed the 'var'
18650     c7 0/subop/copy *Curr-block-depth 1/imm32
18651     # var out/esi: (handle stmt)
18652     68/push 0/imm32
18653     68/push 0/imm32
18654     89/<- %esi 4/r32/esp
18655     # var vars/ecx: (stack (addr var) 16)
18656     81 5/subop/subtract %esp 0xc0/imm32
18657     68/push 0xc0/imm32/size
18658     68/push 0/imm32/top
18659     89/<- %ecx 4/r32/esp
18660     (clear-stack %ecx)
18661     # convert
18662     (parse-mu-var-def _test-input-stream %ecx %esi 0 Stderr 0)
18663     # var out-addr/esi: (addr stmt)
18664     (lookup *esi *(esi+4))  # => eax
18665     89/<- %esi 0/r32/eax
18666     #
18667     (check-ints-equal *esi 2 "F - test-parse-mu-var-def/tag")  # Stmt-tag is var-def
18668     # var v/ecx: (addr var) = lookup(out->var)
18669     (lookup *(esi+4) *(esi+8))  # Vardef-var Vardef-var => eax
18670     89/<- %ecx 0/r32/eax
18671     # v->name
18672     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
18673     (check-strings-equal %eax "n" "F - test-parse-mu-var-def/var-name")
18674     # v->register
18675     (check-ints-equal *(ecx+0x18) 0 "F - test-parse-mu-var-def/var-register")  # Var-register
18676     # v->block-depth
18677     (check-ints-equal *(ecx+0x10) 1 "F - test-parse-mu-var-def/output-block-depth")  # Var-block-depth
18678     # v->type == int
18679     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
18680     (check-ints-equal *eax 1 "F - test-parse-mu-var-def/var-type:0")  # Type-tree-is-atom
18681     (check-ints-equal *(eax+4) 1 "F - test-parse-mu-var-def/var-type:1")  # Type-tree-value
18682     (check-ints-equal *(eax+0xc) 0 "F - test-parse-mu-var-def/var-type:2")  # Type-tree-right
18683     # . epilogue
18684     89/<- %esp 5/r32/ebp
18685     5d/pop-to-ebp
18686     c3/return
18687 
18688 test-parse-mu-reg-var-def:
18689     # 'var n/eax: int <- copy 0'
18690     # . prologue
18691     55/push-ebp
18692     89/<- %ebp 4/r32/esp
18693     # setup
18694     8b/-> *Primitive-type-ids 0/r32/eax
18695     89/<- *Type-id 0/r32/eax  # stream-write
18696     (clear-stream _test-input-stream)
18697     (write _test-input-stream "n/eax: int <- copy 0\n")  # caller has consumed the 'var'
18698     c7 0/subop/copy *Curr-block-depth 1/imm32
18699     # var out/esi: (handle stmt)
18700     68/push 0/imm32
18701     68/push 0/imm32
18702     89/<- %esi 4/r32/esp
18703     # var vars/ecx: (stack (addr var) 16)
18704     81 5/subop/subtract %esp 0xc0/imm32
18705     68/push 0xc0/imm32/size
18706     68/push 0/imm32/top
18707     89/<- %ecx 4/r32/esp
18708     (clear-stack %ecx)
18709     # convert
18710     (parse-mu-var-def _test-input-stream %ecx %esi 0 Stderr 0)
18711     # var out-addr/esi: (addr stmt)
18712     (lookup *esi *(esi+4))  # => eax
18713     89/<- %esi 0/r32/eax
18714     #
18715     (check-ints-equal *esi 3 "F - test-parse-mu-reg-var-def/tag")  # Stmt-tag is reg-var-def
18716     # var v/ecx: (addr var) = lookup(out->outputs->value)
18717     # . eax: (addr stmt-var) = lookup(out->outputs)
18718     (lookup *(esi+0x14) *(esi+0x18))  # Regvardef-outputs Regvardef-outputs => eax
18719     # .
18720     (check-ints-equal *(eax+8) 0 "F - test-parse-mu-reg-var-def/single-output")  # Stmt-var-next
18721     # . eax: (addr var) = lookup(eax->value)
18722     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
18723     # . ecx = eax
18724     89/<- %ecx 0/r32/eax
18725     # v->name
18726     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
18727     (check-strings-equal %eax "n" "F - test-parse-mu-reg-var-def/output-name")  # Var-name
18728     # v->register
18729     (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
18730     (check-strings-equal %eax "eax" "F - test-parse-mu-reg-var-def/output-register")
18731     # v->block-depth
18732     (check-ints-equal *(ecx+0x10) 1 "F - test-parse-mu-reg-var-def/output-block-depth")  # Var-block-depth
18733     # v->type == int
18734     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
18735     (check-ints-equal *eax 1 "F - test-parse-mu-reg-var-def/output-type:0")  # Type-tree-is-atom
18736     (check-ints-equal *(eax+4) 1 "F - test-parse-mu-reg-var-def/output-type:1")  # Type-tree-value
18737     (check-ints-equal *(eax+0xc) 0 "F - test-parse-mu-reg-var-def/output-type:2")  # Type-tree-right
18738     # . epilogue
18739     89/<- %esp 5/r32/ebp
18740     5d/pop-to-ebp
18741     c3/return
18742 
18743 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)
18744     # pseudocode:
18745     #   var name: slice
18746     #   allocate(Heap, Stmt-size, out)
18747     #   var out-addr: (addr stmt) = lookup(*out)
18748     #   out-addr->tag = stmt
18749     #   if stmt-has-outputs?(line)
18750     #     while true
18751     #       name = next-mu-token(line)
18752     #       if (name == '<-') break
18753     #       assert(identifier?(name))
18754     #       var v: (handle var) = lookup-var(name, vars)
18755     #       out-addr->outputs = append(v, out-addr->outputs)
18756     #   add-operation-and-inputs-to-stmt(out-addr, line, vars)
18757     #
18758     # . prologue
18759     55/push-ebp
18760     89/<- %ebp 4/r32/esp
18761     # . save registers
18762     50/push-eax
18763     51/push-ecx
18764     52/push-edx
18765     53/push-ebx
18766     57/push-edi
18767     # var name/ecx: slice
18768     68/push 0/imm32/end
18769     68/push 0/imm32/start
18770     89/<- %ecx 4/r32/esp
18771     # var is-deref?/edx: boolean = false
18772     ba/copy-to-edx 0/imm32/false
18773     # var v: (handle var)
18774     68/push 0/imm32
18775     68/push 0/imm32
18776     89/<- %ebx 4/r32/esp
18777     #
18778     (allocate Heap *Stmt-size *(ebp+0x14))
18779     # var out-addr/edi: (addr stmt) = lookup(*out)
18780     8b/-> *(ebp+0x14) 7/r32/edi
18781     (lookup *edi *(edi+4))  # => eax
18782     89/<- %edi 0/r32/eax
18783     # out-addr->tag = 1/stmt
18784     c7 0/subop/copy *edi 1/imm32/stmt1  # Stmt-tag
18785     {
18786       (stmt-has-outputs? *(ebp+8))
18787       3d/compare-eax-and 0/imm32/false
18788       0f 84/jump-if-= break/disp32
18789       {
18790 $parse-mu-stmt:read-outputs:
18791         # name = next-mu-token(line)
18792         (next-mu-token *(ebp+8) %ecx)
18793         # if slice-empty?(word-slice) break
18794         (slice-empty? %ecx)  # => eax
18795         3d/compare-eax-and 0/imm32/false
18796         0f 85/jump-if-!= break/disp32
18797         # if (name == "<-") break
18798         (slice-equal? %ecx "<-")  # => eax
18799         3d/compare-eax-and 0/imm32/false
18800         0f 85/jump-if-!= break/disp32
18801         # if slice-starts-with?(name, "*") abort
18802         8b/-> *ecx 0/r32/eax  # Slice-start
18803         8a/copy-byte *eax 0/r32/AL
18804         81 4/subop/and %eax 0xff/imm32
18805         3d/compare-eax-and 0x2a/imm32/asterisk
18806         0f 84/jump-if-= $parse-mu-stmt:error-output-dereferenced/disp32
18807         # assert(identifier?(name))
18808         (identifier? %ecx)  # => eax
18809         3d/compare-eax-and 0/imm32/false
18810         0f 84/jump-if-= $parse-mu-stmt:abort/disp32
18811         #
18812         (lookup-var %ecx *(ebp+0xc) %ebx *(ebp+0x10) *(ebp+0x18) *(ebp+0x1c))
18813         8d/copy-address *(edi+0x14) 0/r32/eax  # Stmt1-outputs
18814         (append-stmt-var Heap  *ebx *(ebx+4)  *(edi+0x14) *(edi+0x18)  0  %eax)  # Stmt1-outputs
18815         #
18816         e9/jump loop/disp32
18817       }
18818     }
18819     (add-operation-and-inputs-to-stmt %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x18) *(ebp+0x1c))
18820 $parse-mu-stmt:end:
18821     # . reclaim locals
18822     81 0/subop/add %esp 0x10/imm32
18823     # . restore registers
18824     5f/pop-to-edi
18825     5b/pop-to-ebx
18826     5a/pop-to-edx
18827     59/pop-to-ecx
18828     58/pop-to-eax
18829     # . epilogue
18830     89/<- %esp 5/r32/ebp
18831     5d/pop-to-ebp
18832     c3/return
18833 
18834 $parse-mu-stmt:abort:
18835     # error("invalid identifier '" name "'\n")
18836     (write-buffered *(ebp+0x18) "fn ")
18837     8b/-> *(ebp+0x10) 0/r32/eax
18838     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18839     (write-buffered *(ebp+0x18) %eax)
18840     (write-buffered *(ebp+0x18) ": invalid identifier '")
18841     (write-slice-buffered *(ebp+0x18) %ecx)
18842     (write-buffered *(ebp+0x18) "'\n")
18843     (flush *(ebp+0x18))
18844     (stop *(ebp+0x1c) 1)
18845     # never gets here
18846 
18847 $parse-mu-stmt:error-output-dereferenced:
18848     # error("invalid identifier '" name "'\n")
18849     (write-buffered *(ebp+0x18) "fn ")
18850     8b/-> *(ebp+0x10) 0/r32/eax
18851     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18852     (write-buffered *(ebp+0x18) %eax)
18853     (write-buffered *(ebp+0x18) ": output '")
18854     (write-slice-buffered *(ebp+0x18) %ecx)
18855     (write-buffered *(ebp+0x18) "' should write to a register, and therefore cannot be dereferenced\n")
18856     (flush *(ebp+0x18))
18857     (stop *(ebp+0x1c) 1)
18858     # never gets here
18859 
18860 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)
18861     # pseudocode:
18862     #   stmt->name = slice-to-string(next-mu-token(line))
18863     #   while true
18864     #     name = next-mu-token(line)
18865     #     v = lookup-var-or-literal(name)
18866     #     stmt->inouts = append(v, stmt->inouts)
18867     #
18868     # . prologue
18869     55/push-ebp
18870     89/<- %ebp 4/r32/esp
18871     # . save registers
18872     50/push-eax
18873     51/push-ecx
18874     52/push-edx
18875     53/push-ebx
18876     56/push-esi
18877     57/push-edi
18878     # edi = stmt
18879     8b/-> *(ebp+8) 7/r32/edi
18880     # var name/ecx: slice
18881     68/push 0/imm32/end
18882     68/push 0/imm32/start
18883     89/<- %ecx 4/r32/esp
18884     # var is-deref?/edx: boolean = false
18885     ba/copy-to-edx 0/imm32/false
18886     # var v/esi: (handle var)
18887     68/push 0/imm32
18888     68/push 0/imm32
18889     89/<- %esi 4/r32/esp
18890 $add-operation-and-inputs-to-stmt:read-operation:
18891     (next-mu-token *(ebp+0xc) %ecx)
18892     8d/copy-address *(edi+4) 0/r32/eax  # Stmt1-operation or Regvardef-operationStmt1-operation or Regvardef-operation
18893     (slice-to-string Heap %ecx %eax)
18894     # var is-get?/ebx: boolean = (name == "get")
18895     (slice-equal? %ecx "get")  # => eax
18896     89/<- %ebx 0/r32/eax
18897     {
18898 $add-operation-and-inputs-to-stmt:read-inouts:
18899       # name = next-mu-token(line)
18900       (next-mu-token *(ebp+0xc) %ecx)
18901       # if slice-empty?(word-slice) break
18902       (slice-empty? %ecx)  # => eax
18903       3d/compare-eax-and 0/imm32/false
18904       0f 85/jump-if-!= break/disp32
18905       # if (name == "<-") abort
18906       (slice-equal? %ecx "<-")
18907       3d/compare-eax-and 0/imm32/false
18908       0f 85/jump-if-!= $add-operation-and-inputs-to-stmt:abort/disp32
18909       # if (get? && second operand) lookup or create offset
18910       {
18911         81 7/subop/compare %ebx 0/imm32/false
18912         74/jump-if-= break/disp8
18913         (lookup *(edi+0xc) *(edi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
18914         3d/compare-eax-and 0/imm32
18915         74/jump-if-= break/disp8
18916         (lookup-or-create-constant %eax %ecx %esi)
18917 #?         (lookup *esi *(esi+4))
18918 #?         (write-buffered Stderr "creating new output var ")
18919 #?         (write-int32-hex-buffered Stderr %eax)
18920 #?         (write-buffered Stderr " for field called ")
18921 #?         (write-slice-buffered Stderr %ecx)
18922 #?         (write-buffered Stderr "; var name ")
18923 #?         (lookup *eax *(eax+4))  # Var-name
18924 #?         (write-buffered Stderr %eax)
18925 #?         (write-buffered Stderr Newline)
18926 #?         (flush Stderr)
18927         e9/jump $add-operation-and-inputs-to-stmt:save-var/disp32
18928       }
18929       # is-deref? = false
18930       ba/copy-to-edx 0/imm32/false
18931       # if (slice-starts-with?(name, '*')) ++name->start and set is-deref?
18932       8b/-> *ecx 0/r32/eax  # Slice-start
18933       8a/copy-byte *eax 0/r32/AL
18934       81 4/subop/and %eax 0xff/imm32
18935       3d/compare-eax-and 0x2a/imm32/asterisk
18936       {
18937         75/jump-if-!= break/disp8
18938 $add-operation-and-inputs-to-stmt:inout-is-deref:
18939         ff 0/subop/increment *ecx
18940         ba/copy-to-edx 1/imm32/true
18941       }
18942       (lookup-var-or-literal %ecx *(ebp+0x10) %esi *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
18943       # if (deref?) some additional checks
18944       81 7/subop/compare %edx 0/imm32/false
18945       {
18946         74/jump-if-= break/disp8
18947         # if var is not in register, abort
18948         (lookup *esi *(esi+4))  # => eax
18949         81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
18950         0f 84/jump-if-= $add-operation-and-inputs-to-stmt:error-deref-on-stack/disp32
18951         # if var is not an address, abort
18952         (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
18953         (mu-addr-type? %eax)  # => eax
18954         3d/compare-eax-and 0/imm32/false
18955         0f 84/jump-if-= $add-operation-and-inputs-to-stmt:error-deref-non-addr/disp32
18956       }
18957 $add-operation-and-inputs-to-stmt:save-var:
18958       8d/copy-address *(edi+0xc) 0/r32/eax
18959       (append-stmt-var Heap  *esi *(esi+4)  *(edi+0xc) *(edi+0x10)  %edx  %eax)  # Stmt1-inouts or Regvardef-inouts
18960       #
18961       e9/jump loop/disp32
18962     }
18963 $add-operation-and-inputs-to-stmt:end:
18964     # . reclaim locals
18965     81 0/subop/add %esp 0x10/imm32
18966     # . restore registers
18967     5f/pop-to-edi
18968     5e/pop-to-esi
18969     5b/pop-to-ebx
18970     5a/pop-to-edx
18971     59/pop-to-ecx
18972     58/pop-to-eax
18973     # . epilogue
18974     89/<- %esp 5/r32/ebp
18975     5d/pop-to-ebp
18976     c3/return
18977 
18978 $add-operation-and-inputs-to-stmt:abort:
18979     # error("fn ___: invalid identifier in '" line "'\n")
18980     (write-buffered *(ebp+0x18) "fn ")
18981     8b/-> *(ebp+0x14) 0/r32/eax
18982     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18983     (write-buffered *(ebp+0x18) %eax)
18984     (rewind-stream *(ebp+0xc))
18985     (write-buffered *(ebp+0x18) ": invalid identifier in '")
18986     (write-stream-data *(ebp+0x18) *(ebp+0xc))
18987     (write-buffered *(ebp+0x18) "'\n")
18988     (flush *(ebp+0x18))
18989     (stop *(ebp+0x1c) 1)
18990     # never gets here
18991 
18992 $add-operation-and-inputs-to-stmt:error-deref-on-stack:
18993     # error("fn ___: cannot dereference var ___ on stack\n")
18994     (write-buffered *(ebp+0x18) "fn ")
18995     8b/-> *(ebp+0x14) 0/r32/eax
18996     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18997     (write-buffered *(ebp+0x18) %eax)
18998     (rewind-stream *(ebp+0xc))
18999     (write-buffered *(ebp+0x18) ": cannot dereference var '")
19000     (lookup *esi *(esi+4))  # => eax
19001     (lookup *eax *(eax+4))  # Var-name Var-name => eax
19002     (write-buffered *(ebp+0x18) %eax)
19003     (write-buffered *(ebp+0x18) "' on stack\n")
19004     (flush *(ebp+0x18))
19005     (stop *(ebp+0x1c) 1)
19006     # never gets here
19007 
19008 $add-operation-and-inputs-to-stmt:error-deref-non-addr:
19009     # error("fn ___: cannot dereference non-addr var ___\n")
19010     (write-buffered *(ebp+0x18) "fn ")
19011     8b/-> *(ebp+0x14) 0/r32/eax
19012     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19013     (write-buffered *(ebp+0x18) %eax)
19014     (rewind-stream *(ebp+0xc))
19015     (write-buffered *(ebp+0x18) ": cannot dereference non-addr var '")
19016     (lookup *esi *(esi+4))  # => eax
19017     (lookup *eax *(eax+4))  # Var-name Var-name => eax
19018     (write-buffered *(ebp+0x18) %eax)
19019     (write-buffered *(ebp+0x18) "'\n")
19020     (flush *(ebp+0x18))
19021     (stop *(ebp+0x1c) 1)
19022     # never gets here
19023 
19024 stmt-has-outputs?:  # line: (addr stream byte) -> result/eax: boolean
19025     # . prologue
19026     55/push-ebp
19027     89/<- %ebp 4/r32/esp
19028     # . save registers
19029     51/push-ecx
19030     # var word-slice/ecx: slice
19031     68/push 0/imm32/end
19032     68/push 0/imm32/start
19033     89/<- %ecx 4/r32/esp
19034     # result = false
19035     b8/copy-to-eax 0/imm32/false
19036     (rewind-stream *(ebp+8))
19037     {
19038       (next-mu-token *(ebp+8) %ecx)
19039       # if slice-empty?(word-slice) break
19040       (slice-empty? %ecx)
19041       3d/compare-eax-and 0/imm32/false
19042       b8/copy-to-eax 0/imm32/false/result  # restore result (if we're here it's still false)
19043       0f 85/jump-if-!= break/disp32
19044       # if slice-starts-with?(word-slice, '#') break
19045       # . eax = *word-slice->start
19046       8b/-> *ecx 0/r32/eax
19047       8a/copy-byte *eax 0/r32/AL
19048       81 4/subop/and %eax 0xff/imm32
19049       # . if (eax == '#') break
19050       3d/compare-eax-and 0x23/imm32/hash
19051       b8/copy-to-eax 0/imm32/false/result  # restore result (if we're here it's still false)
19052       0f 84/jump-if-= break/disp32
19053       # if slice-equal?(word-slice, '<-') return true
19054       (slice-equal? %ecx "<-")
19055       3d/compare-eax-and 0/imm32/false
19056       74/jump-if-= loop/disp8
19057       b8/copy-to-eax 1/imm32/true
19058     }
19059 $stmt-has-outputs:end:
19060     (rewind-stream *(ebp+8))
19061     # . reclaim locals
19062     81 0/subop/add %esp 8/imm32
19063     # . restore registers
19064     59/pop-to-ecx
19065     # . epilogue
19066     89/<- %esp 5/r32/ebp
19067     5d/pop-to-ebp
19068     c3/return
19069 
19070 # if 'name' starts with a digit, create a new literal var for it
19071 # otherwise return first 'name' from the top (back) of 'vars' and abort if not found
19072 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)
19073     # . prologue
19074     55/push-ebp
19075     89/<- %ebp 4/r32/esp
19076     # . save registers
19077     50/push-eax
19078     51/push-ecx
19079     56/push-esi
19080     # esi = name
19081     8b/-> *(ebp+8) 6/r32/esi
19082     # if slice-empty?(name) abort
19083     (slice-empty? %esi)  # => eax
19084     3d/compare-eax-and 0/imm32/false
19085     0f 85/jump-if-!= $lookup-var-or-literal:abort/disp32
19086     # var c/ecx: byte = *name->start
19087     8b/-> *esi 1/r32/ecx
19088     8a/copy-byte *ecx 1/r32/CL
19089     81 4/subop/and %ecx 0xff/imm32
19090     # if (decimal-digit?(c) || c == '-') return new var(name)
19091     {
19092       81 7/subop/compare %ecx 0x2d/imm32/dash
19093       74/jump-if-= $lookup-var-or-literal:literal/disp8
19094       (decimal-digit? %ecx)  # => eax
19095       3d/compare-eax-and 0/imm32/false
19096       74/jump-if-= break/disp8
19097 $lookup-var-or-literal:literal:
19098       (new-literal-integer Heap %esi *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
19099       eb/jump $lookup-var-or-literal:end/disp8
19100     }
19101     # else if (c == '"') return new var(name)
19102     {
19103       81 7/subop/compare %ecx 0x22/imm32/dquote
19104       75/jump-if-!= break/disp8
19105 $lookup-var-or-literal:literal-string:
19106       (new-literal-string Heap %esi *(ebp+0x10))
19107       eb/jump $lookup-var-or-literal:end/disp8
19108     }
19109     # otherwise return lookup-var(name, vars)
19110     {
19111 $lookup-var-or-literal:var:
19112       (lookup-var %esi *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
19113     }
19114 $lookup-var-or-literal:end:
19115     # . restore registers
19116     5e/pop-to-esi
19117     59/pop-to-ecx
19118     58/pop-to-eax
19119     # . epilogue
19120     89/<- %esp 5/r32/ebp
19121     5d/pop-to-ebp
19122     c3/return
19123 
19124 $lookup-var-or-literal:abort:
19125     (write-buffered *(ebp+0x18) "fn ")
19126     8b/-> *(ebp+0x14) 0/r32/eax
19127     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19128     (write-buffered *(ebp+0x18) %eax)
19129     (write-buffered *(ebp+0x18) ": empty variable!")
19130     (flush *(ebp+0x18))
19131     (stop *(ebp+0x1c) 1)
19132     # never gets here
19133 
19134 # return first 'name' from the top (back) of 'vars' and abort if not found
19135 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)
19136     # . prologue
19137     55/push-ebp
19138     89/<- %ebp 4/r32/esp
19139     # . save registers
19140     50/push-eax
19141     #
19142     (lookup-var-helper *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
19143     # if (*out == 0) abort
19144     8b/-> *(ebp+0x10) 0/r32/eax
19145     81 7/subop/compare *eax 0/imm32
19146     74/jump-if-= $lookup-var:abort/disp8
19147 $lookup-var:end:
19148     # . restore registers
19149     58/pop-to-eax
19150     # . epilogue
19151     89/<- %esp 5/r32/ebp
19152     5d/pop-to-ebp
19153     c3/return
19154 
19155 $lookup-var:abort:
19156     (write-buffered *(ebp+0x18) "fn ")
19157     8b/-> *(ebp+0x14) 0/r32/eax
19158     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19159     (write-buffered *(ebp+0x18) %eax)
19160     (write-buffered *(ebp+0x18) ": unknown variable '")
19161     (write-slice-buffered *(ebp+0x18) *(ebp+8))
19162     (write-buffered *(ebp+0x18) "'\n")
19163     (flush *(ebp+0x18))
19164     (stop *(ebp+0x1c) 1)
19165     # never gets here
19166 
19167 # return first 'name' from the top (back) of 'vars', and 0/null if not found
19168 # ensure that 'name' if in a register is the topmost variable in that register
19169 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)
19170     # pseudocode:
19171     #   var curr: (addr handle var) = &vars->data[vars->top - 12]
19172     #   var min = vars->data
19173     #   while curr >= min
19174     #     var v: (handle var) = *curr
19175     #     if v->name == name
19176     #       return
19177     #     curr -= 12
19178     #
19179     # . prologue
19180     55/push-ebp
19181     89/<- %ebp 4/r32/esp
19182     # . save registers
19183     50/push-eax
19184     51/push-ecx
19185     52/push-edx
19186     53/push-ebx
19187     56/push-esi
19188     57/push-edi
19189     # clear out
19190     (zero-out *(ebp+0x10) *Handle-size)
19191     # esi = vars
19192     8b/-> *(ebp+0xc) 6/r32/esi
19193     # ebx = vars->top
19194     8b/-> *esi 3/r32/ebx
19195     # if (vars->top > vars->size) abort
19196     3b/compare<- *(esi+4) 0/r32/eax
19197     0f 8f/jump-if-> $lookup-var-helper:error1/disp32
19198     # var min/edx: (addr handle var) = vars->data
19199     8d/copy-address *(esi+8) 2/r32/edx
19200     # var curr/ebx: (addr handle var) = &vars->data[vars->top - 12]
19201     8d/copy-address *(esi+ebx-4) 3/r32/ebx  # vars + 8 + vars->type - 12
19202     # var var-in-reg/edi: 16 addrs
19203     68/push 0/imm32
19204     68/push 0/imm32
19205     68/push 0/imm32
19206     68/push 0/imm32
19207     68/push 0/imm32
19208     68/push 0/imm32
19209     68/push 0/imm32
19210     68/push 0/imm32
19211     68/push 0/imm32
19212     68/push 0/imm32
19213     68/push 0/imm32
19214     68/push 0/imm32
19215     68/push 0/imm32
19216     68/push 0/imm32
19217     68/push 0/imm32
19218     68/push 0/imm32
19219     89/<- %edi 4/r32/esp
19220     {
19221 $lookup-var-helper:loop:
19222       # if (curr < min) return
19223       39/compare %ebx 2/r32/edx
19224       0f 82/jump-if-addr< break/disp32
19225       # var v/ecx: (addr var) = lookup(*curr)
19226       (lookup *ebx *(ebx+4))  # => eax
19227       89/<- %ecx 0/r32/eax
19228       # var vn/eax: (addr array byte) = lookup(v->name)
19229       (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
19230       # if (vn == name) return curr
19231       (slice-equal? *(ebp+8) %eax)  # => eax
19232       3d/compare-eax-and 0/imm32/false
19233       {
19234         74/jump-if-= break/disp8
19235 $lookup-var-helper:found:
19236         # var vr/eax: (addr array byte) = lookup(v->register)
19237         (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
19238         3d/compare-eax-and 0/imm32
19239         {
19240           74/jump-if-= break/disp8
19241 $lookup-var-helper:found-register:
19242           # var reg/eax: int = get(Registers, vr)
19243           (get Mu-registers-unique %eax 0xc "Mu-registers-unique")  # => eax
19244           8b/-> *eax 0/r32/eax
19245           # if (var-in-reg[reg]) error
19246           8b/-> *(edi+eax<<2) 0/r32/eax
19247           3d/compare-eax-and 0/imm32
19248           0f 85/jump-if-!= $lookup-var-helper:error2/disp32
19249         }
19250 $lookup-var-helper:return:
19251         # esi = out
19252         8b/-> *(ebp+0x10) 6/r32/esi
19253         # *out = *curr
19254         8b/-> *ebx 0/r32/eax
19255         89/<- *esi 0/r32/eax
19256         8b/-> *(ebx+4) 0/r32/eax
19257         89/<- *(esi+4) 0/r32/eax
19258         # return
19259         eb/jump $lookup-var-helper:end/disp8
19260       }
19261       # 'name' not yet found; update var-in-reg if v in register
19262       # . var vr/eax: (addr array byte) = lookup(v->register)
19263       (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
19264       # . if (vr == 0) continue
19265       3d/compare-eax-and 0/imm32
19266       74/jump-if-= $lookup-var-helper:continue/disp8
19267       # . var reg/eax: int = get(Registers, vr)
19268       (get Mu-registers-unique %eax 0xc "Mu-registers-unique")  # => eax
19269       8b/-> *eax 0/r32/eax
19270       # . var-in-reg[reg] = v
19271       89/<- *(edi+eax<<2) 1/r32/ecx
19272 $lookup-var-helper:continue:
19273       # curr -= 12
19274       81 5/subop/subtract %ebx 0xc/imm32
19275       e9/jump loop/disp32
19276     }
19277 $lookup-var-helper:end:
19278     # . reclaim locals
19279     81 0/subop/add %esp 0x40/imm32
19280     # . restore registers
19281     5f/pop-to-edi
19282     5e/pop-to-esi
19283     5b/pop-to-ebx
19284     5a/pop-to-edx
19285     59/pop-to-ecx
19286     58/pop-to-eax
19287     # . epilogue
19288     89/<- %esp 5/r32/ebp
19289     5d/pop-to-ebp
19290     c3/return
19291 
19292 $lookup-var-helper:error1:
19293     (write-buffered *(ebp+0x18) "fn ")
19294     8b/-> *(ebp+0x14) 0/r32/eax
19295     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19296     (write-buffered *(ebp+0x18) %eax)
19297     (write-buffered *(ebp+0x18) ": malformed stack when looking up '")
19298     (write-slice-buffered *(ebp+0x18) *(ebp+8))
19299     (write-buffered *(ebp+0x18) "'\n")
19300     (flush *(ebp+0x18))
19301     (stop *(ebp+0x1c) 1)
19302     # never gets here
19303 
19304 $lookup-var-helper:error2:
19305     # eax contains the conflicting var at this point
19306     (write-buffered *(ebp+0x18) "fn ")
19307     50/push-eax
19308     8b/-> *(ebp+0x14) 0/r32/eax
19309     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19310     (write-buffered *(ebp+0x18) %eax)
19311     58/pop-eax
19312     (write-buffered *(ebp+0x18) ": register ")
19313     50/push-eax
19314     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
19315     (write-buffered *(ebp+0x18) %eax)
19316     58/pop-to-eax
19317     (write-buffered *(ebp+0x18) " reads var '")
19318     (write-slice-buffered *(ebp+0x18) *(ebp+8))
19319     (write-buffered *(ebp+0x18) "' after writing var '")
19320     (lookup *eax *(eax+4))  # Var-name Var-name => eax
19321     (write-buffered *(ebp+0x18) %eax)
19322     (write-buffered *(ebp+0x18) "'\n")
19323     (flush *(ebp+0x18))
19324     (stop *(ebp+0x1c) 1)
19325     # never gets here
19326 
19327 dump-vars:  # vars: (addr stack live-var)
19328     # pseudocode:
19329     #   var curr: (addr handle var) = &vars->data[vars->top - 12]
19330     #   var min = vars->data
19331     #   while curr >= min
19332     #     var v: (handle var) = *curr
19333     #     print v
19334     #     curr -= 12
19335     #
19336     # . prologue
19337     55/push-ebp
19338     89/<- %ebp 4/r32/esp
19339     # . save registers
19340     52/push-edx
19341     53/push-ebx
19342     56/push-esi
19343     # esi = vars
19344     8b/-> *(ebp+8) 6/r32/esi
19345     # ebx = vars->top
19346     8b/-> *esi 3/r32/ebx
19347     # var min/edx: (addr handle var) = vars->data
19348     8d/copy-address *(esi+8) 2/r32/edx
19349     # var curr/ebx: (addr handle var) = &vars->data[vars->top - 12]
19350     8d/copy-address *(esi+ebx-4) 3/r32/ebx  # vars + 8 + vars->type - 12
19351     {
19352 $dump-vars:loop:
19353       # if (curr < min) return
19354       39/compare %ebx 2/r32/edx
19355       0f 82/jump-if-addr< break/disp32
19356       #
19357       (write-buffered Stderr "  var@")
19358       (dump-var 2 %ebx)
19359       # curr -= 12
19360       81 5/subop/subtract %ebx 0xc/imm32
19361       e9/jump loop/disp32
19362     }
19363 $dump-vars:end:
19364     # . restore registers
19365     5e/pop-to-esi
19366     5b/pop-to-ebx
19367     5a/pop-to-edx
19368     # . epilogue
19369     89/<- %esp 5/r32/ebp
19370     5d/pop-to-ebp
19371     c3/return
19372 
19373 == data
19374 # Like Registers, but no esp or ebp
19375 Mu-registers:  # (addr stream {(handle array byte), int})
19376   # a table is a stream
19377   0xa8/imm32/write
19378   0/imm32/read
19379   0xa8/imm32/length
19380   # data
19381   # general-purpose registers
19382   # it is perfectly ok to use fake alloc-ids -- as long as you never try to reclaim them
19383   0x11/imm32/alloc-id $Mu-register-eax/imm32 0/imm32
19384   0x11/imm32/alloc-id $Mu-register-ecx/imm32 1/imm32
19385   0x11/imm32/alloc-id $Mu-register-edx/imm32 2/imm32
19386   0x11/imm32/alloc-id $Mu-register-ebx/imm32 3/imm32
19387   0x11/imm32/alloc-id $Mu-register-esi/imm32 6/imm32
19388   0x11/imm32/alloc-id $Mu-register-edi/imm32 7/imm32
19389   # floating-point registers
19390   0x11/imm32/alloc-id $Mu-register-xmm0/imm32 0/imm32
19391   0x11/imm32/alloc-id $Mu-register-xmm1/imm32 1/imm32
19392   0x11/imm32/alloc-id $Mu-register-xmm2/imm32 2/imm32
19393   0x11/imm32/alloc-id $Mu-register-xmm3/imm32 3/imm32
19394   0x11/imm32/alloc-id $Mu-register-xmm4/imm32 4/imm32
19395   0x11/imm32/alloc-id $Mu-register-xmm5/imm32 5/imm32
19396   0x11/imm32/alloc-id $Mu-register-xmm6/imm32 6/imm32
19397   0x11/imm32/alloc-id $Mu-register-xmm7/imm32 7/imm32
19398 
19399 # Like Mu-registers, but with unique codes for integer and floating-point
19400 # registers.
19401 # Don't use this for code-generation, only for checking.
19402 Mu-registers-unique:  # (addr stream {(handle array byte), int})
19403   # a table is a stream
19404   0xa8/imm32/write
19405   0/imm32/read
19406   0xa8/imm32/length
19407   # data
19408   # general-purpose registers
19409   0x11/imm32/alloc-id $Mu-register-eax/imm32 0/imm32
19410   0x11/imm32/alloc-id $Mu-register-ecx/imm32 1/imm32
19411   0x11/imm32/alloc-id $Mu-register-edx/imm32 2/imm32
19412   0x11/imm32/alloc-id $Mu-register-ebx/imm32 3/imm32
19413   0x11/imm32/alloc-id $Mu-register-esi/imm32 6/imm32
19414   0x11/imm32/alloc-id $Mu-register-edi/imm32 7/imm32
19415   # floating-point registers
19416   0x11/imm32/alloc-id $Mu-register-xmm0/imm32 8/imm32
19417   0x11/imm32/alloc-id $Mu-register-xmm1/imm32 9/imm32
19418   0x11/imm32/alloc-id $Mu-register-xmm2/imm32 0xa/imm32
19419   0x11/imm32/alloc-id $Mu-register-xmm3/imm32 0xb/imm32
19420   0x11/imm32/alloc-id $Mu-register-xmm4/imm32 0xc/imm32
19421   0x11/imm32/alloc-id $Mu-register-xmm5/imm32 0xd/imm32
19422   0x11/imm32/alloc-id $Mu-register-xmm6/imm32 0xe/imm32
19423   0x11/imm32/alloc-id $Mu-register-xmm7/imm32 0xf/imm32
19424 
19425 $Mu-register-eax:
19426   0x11/imm32/alloc-id
19427   3/imm32/size
19428   0x65/e 0x61/a 0x78/x
19429 
19430 $Mu-register-ecx:
19431   0x11/imm32/alloc-id
19432   3/imm32/size
19433   0x65/e 0x63/c 0x78/x
19434 
19435 $Mu-register-edx:
19436   0x11/imm32/alloc-id
19437   3/imm32/size
19438   0x65/e 0x64/d 0x78/x
19439 
19440 $Mu-register-ebx:
19441   0x11/imm32/alloc-id
19442   3/imm32/size
19443   0x65/e 0x62/b 0x78/x
19444 
19445 $Mu-register-esi:
19446   0x11/imm32/alloc-id
19447   3/imm32/size
19448   0x65/e 0x73/s 0x69/i
19449 
19450 $Mu-register-edi:
19451   0x11/imm32/alloc-id
19452   3/imm32/size
19453   0x65/e 0x64/d 0x69/i
19454 
19455 $Mu-register-xmm0:
19456   0x11/imm32/alloc-id:fake:payload
19457   # "xmm0"
19458   0x4/imm32/size
19459   0x78/x 0x6d/m 0x6d/m 0x30/0
19460 
19461 $Mu-register-xmm1:
19462   0x11/imm32/alloc-id:fake:payload
19463   # "xmm1"
19464   0x4/imm32/size
19465   0x78/x 0x6d/m 0x6d/m 0x31/1
19466 
19467 $Mu-register-xmm2:
19468   0x11/imm32/alloc-id:fake:payload
19469   # "xmm2"
19470   0x4/imm32/size
19471   0x78/x 0x6d/m 0x6d/m 0x32/2
19472 
19473 $Mu-register-xmm3:
19474   0x11/imm32/alloc-id:fake:payload
19475   # "xmm3"
19476   0x4/imm32/size
19477   0x78/x 0x6d/m 0x6d/m 0x33/3
19478 
19479 $Mu-register-xmm4:
19480   0x11/imm32/alloc-id:fake:payload
19481   # "xmm4"
19482   0x4/imm32/size
19483   0x78/x 0x6d/m 0x6d/m 0x34/4
19484 
19485 $Mu-register-xmm5:
19486   0x11/imm32/alloc-id:fake:payload
19487   # "xmm5"
19488   0x4/imm32/size
19489   0x78/x 0x6d/m 0x6d/m 0x35/5
19490 
19491 $Mu-register-xmm6:
19492   0x11/imm32/alloc-id:fake:payload
19493   # "xmm6"
19494   0x4/imm32/size
19495   0x78/x 0x6d/m 0x6d/m 0x36/6
19496 
19497 $Mu-register-xmm7:
19498   0x11/imm32/alloc-id:fake:payload
19499   # "xmm7"
19500   0x4/imm32/size
19501   0x78/x 0x6d/m 0x6d/m 0x37/7
19502 
19503 == code
19504 
19505 # push 'out' to 'vars' if not already there; it's assumed to be a fn output
19506 maybe-define-var:  # out: (handle var), vars: (addr stack live-var)
19507     # . prologue
19508     55/push-ebp
19509     89/<- %ebp 4/r32/esp
19510     # . save registers
19511     50/push-eax
19512     # var out-addr/eax: (addr var)
19513     (lookup *(ebp+8) *(ebp+0xc))  # => eax
19514     #
19515     (binding-exists? %eax *(ebp+0x10))  # => eax
19516     3d/compare-eax-and 0/imm32/false
19517     75/jump-if-!= $maybe-define-var:end/disp8
19518     # otherwise update vars
19519     (push *(ebp+0x10) *(ebp+8))
19520     (push *(ebp+0x10) *(ebp+0xc))
19521     (push *(ebp+0x10) 0)  # 'out' is always a fn output; never spill it
19522 $maybe-define-var:end:
19523     # . restore registers
19524     58/pop-to-eax
19525     # . epilogue
19526     89/<- %esp 5/r32/ebp
19527     5d/pop-to-ebp
19528     c3/return
19529 
19530 # simpler version of lookup-var-helper
19531 binding-exists?:  # target: (addr var), vars: (addr stack live-var) -> result/eax: boolean
19532     # pseudocode:
19533     #   var curr: (addr handle var) = &vars->data[vars->top - 12]
19534     #   var min = vars->data
19535     #   while curr >= min
19536     #     var v: (handle var) = *curr
19537     #     if v->name == target->name
19538     #       return true
19539     #     curr -= 12
19540     #   return false
19541     #
19542     # . prologue
19543     55/push-ebp
19544     89/<- %ebp 4/r32/esp
19545     # . save registers
19546     51/push-ecx
19547     52/push-edx
19548     56/push-esi
19549     # var target-name/ecx: (addr array byte) = lookup(target->name)
19550     8b/-> *(ebp+8) 0/r32/eax
19551     (lookup *eax *(eax+4))  # Var-name Var-name => eax
19552     89/<- %ecx 0/r32/eax
19553     # esi = vars
19554     8b/-> *(ebp+0xc) 6/r32/esi
19555     # eax = vars->top
19556     8b/-> *esi 0/r32/eax
19557     # var min/edx: (addr handle var) = vars->data
19558     8d/copy-address *(esi+8) 2/r32/edx
19559     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
19560     8d/copy-address *(esi+eax-4) 6/r32/esi  # vars + 8 + vars->type - 12
19561     {
19562 $binding-exists?:loop:
19563       # if (curr < min) return
19564       39/compare %esi 2/r32/edx
19565       0f 82/jump-if-addr< break/disp32
19566       # var v/eax: (addr var) = lookup(*curr)
19567       (lookup *esi *(esi+4))  # => eax
19568       # var vn/eax: (addr array byte) = lookup(v->name)
19569       (lookup *eax *(eax+4))  # Var-name Var-name => eax
19570       # if (vn == target-name) return true
19571       (string-equal? %ecx %eax)  # => eax
19572       3d/compare-eax-and 0/imm32/false
19573       75/jump-if-!= $binding-exists?:end/disp8  # eax already contains true
19574       # curr -= 12
19575       81 5/subop/subtract %esi 0xc/imm32
19576       e9/jump loop/disp32
19577     }
19578     b8/copy-to-eax 0/imm32/false
19579 $binding-exists?:end:
19580     # . restore registers
19581     5e/pop-to-esi
19582     5a/pop-to-edx
19583     59/pop-to-ecx
19584     # . epilogue
19585     89/<- %esp 5/r32/ebp
19586     5d/pop-to-ebp
19587     c3/return
19588 
19589 test-parse-mu-stmt:
19590     # . prologue
19591     55/push-ebp
19592     89/<- %ebp 4/r32/esp
19593     # setup
19594     8b/-> *Primitive-type-ids 0/r32/eax
19595     89/<- *Type-id 0/r32/eax  # stream-write
19596     (clear-stream _test-input-stream)
19597     (write _test-input-stream "increment n\n")
19598     # var vars/ecx: (stack (addr var) 16)
19599     81 5/subop/subtract %esp 0xc0/imm32
19600     68/push 0xc0/imm32/size
19601     68/push 0/imm32/top
19602     89/<- %ecx 4/r32/esp
19603     (clear-stack %ecx)
19604     # var v/edx: (handle var)
19605     68/push 0/imm32
19606     68/push 0/imm32
19607     89/<- %edx 4/r32/esp
19608     # var s/eax: (handle array byte)
19609     68/push 0/imm32
19610     68/push 0/imm32
19611     89/<- %eax 4/r32/esp
19612     # v = new var("n")
19613     (copy-array Heap "n" %eax)
19614     (new-var Heap *eax *(eax+4) %edx)
19615     #
19616     (push %ecx *edx)
19617     (push %ecx *(edx+4))
19618     (push %ecx 0)
19619     # var out/eax: (handle stmt)
19620     68/push 0/imm32
19621     68/push 0/imm32
19622     89/<- %eax 4/r32/esp
19623     # convert
19624     (parse-mu-stmt _test-input-stream %ecx 0 %eax Stderr 0)
19625     # var out-addr/edx: (addr stmt) = lookup(*out)
19626     (lookup *eax *(eax+4))  # => eax
19627     89/<- %edx 0/r32/eax
19628     # out->tag
19629     (check-ints-equal *edx 1 "F - test-parse-mu-stmt/tag")  # Stmt-tag is Stmt1
19630     # out->operation
19631     (lookup *(edx+4) *(edx+8))  # Stmt1-operation Stmt1-operation => eax
19632     (check-strings-equal %eax "increment" "F - test-parse-mu-stmt/name")  # Stmt1-operation
19633     # out->inouts->value->name
19634     # . eax = out->inouts
19635     (lookup *(edx+0xc) *(edx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
19636     # . eax = out->inouts->value
19637     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
19638     # . eax = out->inouts->value->name
19639     (lookup *eax *(eax+4))  # Var-name Var-name => eax
19640     # .
19641     (check-strings-equal %eax "n" "F - test-parse-mu-stmt/inout:0")
19642     # . epilogue
19643     89/<- %esp 5/r32/ebp
19644     5d/pop-to-ebp
19645     c3/return
19646 
19647 test-parse-mu-stmt-with-comma:
19648     # . prologue
19649     55/push-ebp
19650     89/<- %ebp 4/r32/esp
19651     # setup
19652     8b/-> *Primitive-type-ids 0/r32/eax
19653     89/<- *Type-id 0/r32/eax  # stream-write
19654     (clear-stream _test-input-stream)
19655     (write _test-input-stream "copy-to n, 3\n")
19656     # var vars/ecx: (stack (addr var) 16)
19657     81 5/subop/subtract %esp 0xc0/imm32
19658     68/push 0xc0/imm32/size
19659     68/push 0/imm32/top
19660     89/<- %ecx 4/r32/esp
19661     (clear-stack %ecx)
19662     # var v/edx: (handle var)
19663     68/push 0/imm32
19664     68/push 0/imm32
19665     89/<- %edx 4/r32/esp
19666     # var s/eax: (handle array byte)
19667     68/push 0/imm32
19668     68/push 0/imm32
19669     89/<- %eax 4/r32/esp
19670     # v = new var("n")
19671     (copy-array Heap "n" %eax)
19672     (new-var Heap *eax *(eax+4) %edx)
19673     #
19674     (push %ecx *edx)
19675     (push %ecx *(edx+4))
19676     (push %ecx 0)
19677     # var out/eax: (handle stmt)
19678     68/push 0/imm32
19679     68/push 0/imm32
19680     89/<- %eax 4/r32/esp
19681     # convert
19682     (parse-mu-stmt _test-input-stream %ecx 0 %eax Stderr 0)
19683     # var out-addr/edx: (addr stmt) = lookup(*out)
19684     (lookup *eax *(eax+4))  # => eax
19685     89/<- %edx 0/r32/eax
19686     # out->tag
19687     (check-ints-equal *edx 1 "F - test-parse-mu-stmt-with-comma/tag")  # Stmt-tag is Stmt1
19688     # out->operation
19689     (lookup *(edx+4) *(edx+8))  # Stmt1-operation Stmt1-operation => eax
19690     (check-strings-equal %eax "copy-to" "F - test-parse-mu-stmt-with-comma/name")  # Stmt1-operation
19691     # out->inouts->value->name
19692     # . eax = out->inouts
19693     (lookup *(edx+0xc) *(edx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
19694     # . eax = out->inouts->value
19695     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
19696     # . eax = out->inouts->value->name
19697     (lookup *eax *(eax+4))  # Var-name Var-name => eax
19698     # .
19699     (check-strings-equal %eax "n" "F - test-parse-mu-stmt-with-comma/inout:0")
19700     # . epilogue
19701     89/<- %esp 5/r32/ebp
19702     5d/pop-to-ebp
19703     c3/return
19704 
19705 new-var:  # ad: (addr allocation-descriptor), name: (handle array byte), out: (addr handle var)
19706     # . prologue
19707     55/push-ebp
19708     89/<- %ebp 4/r32/esp
19709     # . save registers
19710     50/push-eax
19711     51/push-ecx
19712     # ecx = out
19713     8b/-> *(ebp+0x14) 1/r32/ecx
19714     #
19715     (allocate *(ebp+8) *Var-size %ecx)
19716     # var out-addr/eax: (addr var)
19717     (lookup *ecx *(ecx+4))  # => eax
19718     # out-addr->name = name
19719     8b/-> *(ebp+0xc) 1/r32/ecx
19720     89/<- *eax 1/r32/ecx  # Var-name
19721     8b/-> *(ebp+0x10) 1/r32/ecx
19722     89/<- *(eax+4) 1/r32/ecx  # Var-name
19723 #?     (write-buffered Stderr "var ")
19724 #?     (lookup *(ebp+0xc) *(ebp+0x10))
19725 #?     (write-buffered Stderr %eax)
19726 #?     (write-buffered Stderr " at ")
19727 #?     8b/-> *(ebp+0x14) 1/r32/ecx
19728 #?     (lookup *ecx *(ecx+4))  # => eax
19729 #?     (write-int32-hex-buffered Stderr %eax)
19730 #?     (write-buffered Stderr Newline)
19731 #?     (flush Stderr)
19732 $new-var:end:
19733     # . restore registers
19734     59/pop-to-ecx
19735     58/pop-to-eax
19736     # . epilogue
19737     89/<- %esp 5/r32/ebp
19738     5d/pop-to-ebp
19739     c3/return
19740 
19741 # WARNING: modifies name
19742 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)
19743     # . prologue
19744     55/push-ebp
19745     89/<- %ebp 4/r32/esp
19746     # . save registers
19747     50/push-eax
19748     51/push-ecx
19749     # first strip out metadata
19750     8b/-> *(ebp+0xc) 1/r32/ecx
19751     (next-token-from-slice *ecx *(ecx+4) 0x2f *(ebp+0xc))
19752     # if (!is-hex-int?(name)) abort
19753     (hex-int? *(ebp+0xc))  # => eax
19754     3d/compare-eax-and 0/imm32/false
19755     0f 84/jump-if-= $new-literal-integer:abort/disp32
19756     # a little more error-checking
19757     (check-mu-hex-int *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
19758     # out = new var(s)
19759     (new-var-from-slice *(ebp+8) *(ebp+0xc) *(ebp+0x10))
19760     # var out-addr/ecx: (addr var) = lookup(*out)
19761     8b/-> *(ebp+0x10) 0/r32/eax
19762     (lookup *eax *(eax+4))  # => eax
19763     89/<- %ecx 0/r32/eax
19764     # out-addr->block-depth = *Curr-block-depth
19765     8b/-> *Curr-block-depth 0/r32/eax
19766     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
19767     # out-addr->type = new tree()
19768     8d/copy-address *(ecx+8) 0/r32/eax  # Var-type
19769     (allocate *(ebp+8) *Type-tree-size %eax)
19770     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
19771     c7 0/subop/copy *eax 1/imm32/true  # Type-tree-is-atom
19772     # nothing else to do; default type is 'literal'
19773 $new-literal-integer:end:
19774     # . reclaim locals
19775     81 0/subop/add %esp 8/imm32
19776     # . restore registers
19777     59/pop-to-ecx
19778     58/pop-to-eax
19779     # . epilogue
19780     89/<- %esp 5/r32/ebp
19781     5d/pop-to-ebp
19782     c3/return
19783 
19784 $new-literal-integer:abort:
19785     (write-buffered *(ebp+0x18) "fn ")
19786     8b/-> *(ebp+0x14) 0/r32/eax
19787     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19788     (write-buffered *(ebp+0x18) %eax)
19789     (write-buffered *(ebp+0x18) ": variable '")
19790     (write-slice-buffered *(ebp+0x18) *(ebp+0xc))
19791     (write-buffered *(ebp+0x18) "' cannot begin with a digit (or do you have a typo in a number?)\n")
19792     (flush *(ebp+0x18))
19793     (stop *(ebp+0x1c) 1)
19794     # never gets here
19795 
19796 # precondition: name is a valid hex integer; require a '0x' prefix
19797 check-mu-hex-int:  # name: (addr slice), err: (addr buffered-file), ed: (addr exit-descriptor)
19798     # . prologue
19799     55/push-ebp
19800     89/<- %ebp 4/r32/esp
19801     # . save registers
19802     50/push-eax
19803     51/push-ecx
19804     52/push-edx
19805     # ecx = name
19806     8b/-> *(ebp+8) 1/r32/ecx
19807     # var start/edx: (addr byte) = name->start
19808     8b/-> *ecx 2/r32/edx
19809     # if (*start == '-') ++start
19810     b8/copy-to-eax 0/imm32
19811     8a/copy-byte *edx 0/r32/AL
19812     3d/compare-eax-and 0x2d/imm32/dash
19813     {
19814       75/jump-if-!= break/disp8
19815       42/increment-edx
19816     }
19817     # var end/ecx: (addr byte) = name->end
19818     8b/-> *(ecx+4) 1/r32/ecx
19819     # var len/eax: int = name->end - name->start
19820     89/<- %eax 1/r32/ecx
19821     29/subtract-from %eax 2/r32/edx
19822     # if (len <= 1) return
19823     3d/compare-eax-with 1/imm32
19824     0f 8e/jump-if-<= $check-mu-hex-int:end/disp32
19825 $check-mu-hex-int:length->-1:
19826     # if slice-starts-with?({start, end}, "0x") return
19827     # . var tmp = {start, end}
19828     51/push-ecx
19829     52/push-edx
19830     89/<- %eax 4/r32/esp
19831     # .
19832     (slice-starts-with? %eax "0x")  # => eax
19833     # . reclaim tmp
19834     81 0/subop/add %esp 8/imm32
19835     # .
19836     3d/compare-eax-with 0/imm32/false
19837     75/jump-if-!= $check-mu-hex-int:end/disp8
19838 $check-mu-hex-int:abort:
19839     # otherwise abort
19840     (write-buffered *(ebp+0xc) "literal integers are always hex in Mu; start '")
19841     (write-slice-buffered *(ebp+0xc) *(ebp+8))
19842     (write-buffered *(ebp+0xc) "' with a '0x' to be unambiguous, converting it to hexadecimal as necessary.\n")
19843     (flush *(ebp+0xc))
19844     (stop *(ebp+0x10) 1)
19845 $check-mu-hex-int:end:
19846     # . restore registers
19847     5a/pop-to-edx
19848     59/pop-to-ecx
19849     58/pop-to-eax
19850     # . epilogue
19851     89/<- %esp 5/r32/ebp
19852     5d/pop-to-ebp
19853     c3/return
19854 
19855 new-literal:  # ad: (addr allocation-descriptor), name: (addr slice), out: (addr handle var)
19856     # . prologue
19857     55/push-ebp
19858     89/<- %ebp 4/r32/esp
19859     # . save registers
19860     50/push-eax
19861     51/push-ecx
19862     # var s/ecx: (handle array byte)
19863     68/push 0/imm32
19864     68/push 0/imm32
19865     89/<- %ecx 4/r32/esp
19866     # s = slice-to-string(name)
19867     (slice-to-string Heap *(ebp+0xc) %ecx)
19868     # allocate to out
19869     (new-var *(ebp+8) *ecx *(ecx+4) *(ebp+0x10))
19870     # var out-addr/ecx: (addr var) = lookup(*out)
19871     8b/-> *(ebp+0x10) 1/r32/ecx
19872     (lookup *ecx *(ecx+4))  # => eax
19873     89/<- %ecx 0/r32/eax
19874     # out-addr->block-depth = *Curr-block-depth
19875     8b/-> *Curr-block-depth 0/r32/eax
19876     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
19877     # out-addr->type/eax = new type
19878     8d/copy-address *(ecx+8) 0/r32/eax  # Var-type
19879     (allocate *(ebp+8) *Type-tree-size %eax)
19880     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
19881     # nothing else to do; default type is 'literal'
19882     c7 0/subop/copy *eax 1/imm32/true  # Type-tree-is-atom
19883 $new-literal:end:
19884     # . reclaim locals
19885     81 0/subop/add %esp 8/imm32
19886     # . restore registers
19887     59/pop-to-ecx
19888     58/pop-to-eax
19889     # . epilogue
19890     89/<- %esp 5/r32/ebp
19891     5d/pop-to-ebp
19892     c3/return
19893 
19894 new-literal-string:  # ad: (addr allocation-descriptor), name: (addr slice), out: (addr handle var)
19895     # . prologue
19896     55/push-ebp
19897     89/<- %ebp 4/r32/esp
19898     # . save registers
19899     50/push-eax
19900     51/push-ecx
19901     # var s/ecx: (handle array byte)
19902     68/push 0/imm32
19903     68/push 0/imm32
19904     89/<- %ecx 4/r32/esp
19905     # s = slice-to-string(name)
19906     (slice-to-string Heap *(ebp+0xc) %ecx)
19907     # allocate to out
19908     (new-var *(ebp+8) *ecx *(ecx+4) *(ebp+0x10))
19909     # var out-addr/ecx: (addr var) = lookup(*out)
19910     8b/-> *(ebp+0x10) 1/r32/ecx
19911     (lookup *ecx *(ecx+4))  # => eax
19912     89/<- %ecx 0/r32/eax
19913     # out-addr->block-depth = *Curr-block-depth
19914     8b/-> *Curr-block-depth 0/r32/eax
19915     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
19916     # out-addr->type/eax = new type
19917     8d/copy-address *(ecx+8) 0/r32/eax  # Var-type
19918     (allocate *(ebp+8) *Type-tree-size %eax)
19919     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
19920     # out-addr->type->value = literal-string
19921     c7 0/subop/copy *(eax+4) 0x10/imm32/type-id-string-literal  # Type-tree-value
19922     # out-addr->type->is-atom? = true
19923     c7 0/subop/copy *eax 1/imm32/true  # Type-tree-is-atom
19924 $new-literal-string:end:
19925     # . reclaim locals
19926     81 0/subop/add %esp 8/imm32
19927     # . restore registers
19928     59/pop-to-ecx
19929     58/pop-to-eax
19930     # . epilogue
19931     89/<- %esp 5/r32/ebp
19932     5d/pop-to-ebp
19933     c3/return
19934 
19935 new-var-from-slice:  # ad: (addr allocation-descriptor), name: (addr slice), out: (addr handle var)
19936     # . prologue
19937     55/push-ebp
19938     89/<- %ebp 4/r32/esp
19939     # . save registers
19940     51/push-ecx
19941     # var tmp/ecx: (handle array byte)
19942     68/push 0/imm32
19943     68/push 0/imm32
19944     89/<- %ecx 4/r32/esp
19945     # tmp = slice-to-string(name)
19946     (slice-to-string Heap *(ebp+0xc) %ecx)
19947     # out = new-var(tmp)
19948     (new-var *(ebp+8) *ecx *(ecx+4) *(ebp+0x10))
19949 $new-var-from-slice:end:
19950     # . reclaim locals
19951     81 0/subop/add %esp 8/imm32
19952     # . restore registers
19953     59/pop-to-ecx
19954     # . epilogue
19955     89/<- %esp 5/r32/ebp
19956     5d/pop-to-ebp
19957     c3/return
19958 
19959 new-var-def:  # ad: (addr allocation-descriptor), var: (handle var), out: (addr handle stmt)
19960     # . prologue
19961     55/push-ebp
19962     89/<- %ebp 4/r32/esp
19963     # . save registers
19964     50/push-eax
19965     51/push-ecx
19966     #
19967     (allocate *(ebp+8) *Stmt-size *(ebp+0x14))
19968     # var out-addr/eax: (addr stmt) = lookup(*out)
19969     8b/-> *(ebp+0x14) 0/r32/eax
19970     (lookup *eax *(eax+4))  # => eax
19971     # out-addr->tag = stmt
19972     c7 0/subop/copy *eax 2/imm32/tag/var-on-stack  # Stmt-tag
19973     # result->var = var
19974     8b/-> *(ebp+0xc) 1/r32/ecx
19975     89/<- *(eax+4) 1/r32/ecx  # Vardef-var
19976     8b/-> *(ebp+0x10) 1/r32/ecx
19977     89/<- *(eax+8) 1/r32/ecx  # Vardef-var
19978 $new-var-def:end:
19979     # . restore registers
19980     59/pop-to-ecx
19981     58/pop-to-eax
19982     # . epilogue
19983     89/<- %esp 5/r32/ebp
19984     5d/pop-to-ebp
19985     c3/return
19986 
19987 new-reg-var-def:  # ad: (addr allocation-descriptor), var: (handle var), out: (addr handle stmt)
19988     # . prologue
19989     55/push-ebp
19990     89/<- %ebp 4/r32/esp
19991     # . save registers
19992     50/push-eax
19993     # eax = out
19994     8b/-> *(ebp+0x14) 0/r32/eax
19995     #
19996     (allocate *(ebp+8) *Stmt-size %eax)
19997     # var out-addr/eax: (addr stmt) = lookup(*out)
19998     (lookup *eax *(eax+4))  # => eax
19999     # set tag
20000     c7 0/subop/copy *eax 3/imm32/tag/var-in-register  # Stmt-tag
20001     # set output
20002     8d/copy-address *(eax+0x14) 0/r32/eax  # Regvardef-outputs
20003     (append-stmt-var Heap  *(ebp+0xc) *(ebp+0x10)  0 0  0  %eax)
20004 $new-reg-var-def:end:
20005     # . restore registers
20006     58/pop-to-eax
20007     # . epilogue
20008     89/<- %esp 5/r32/ebp
20009     5d/pop-to-ebp
20010     c3/return
20011 
20012 append-list:  # ad: (addr allocation-descriptor), value: (handle _type), list: (handle list _type), out: (addr handle list _type)
20013     # . prologue
20014     55/push-ebp
20015     89/<- %ebp 4/r32/esp
20016     # . save registers
20017     50/push-eax
20018     51/push-ecx
20019     57/push-edi
20020     # edi = out
20021     8b/-> *(ebp+0x1c) 7/r32/edi
20022     # *out = new list
20023     (allocate *(ebp+8) *List-size %edi)
20024     # var out-addr/edi: (addr list _type) = lookup(*out)
20025     (lookup *edi *(edi+4))  # => eax
20026     89/<- %edi 0/r32/eax
20027     # out-addr->value = value
20028     8b/-> *(ebp+0xc) 0/r32/eax
20029     89/<- *edi 0/r32/eax  # List-value
20030     8b/-> *(ebp+0x10) 0/r32/eax
20031     89/<- *(edi+4) 0/r32/eax  # List-value
20032     # if (list == null) return
20033     81 7/subop/compare *(ebp+0x14) 0/imm32
20034     74/jump-if-= $append-list:end/disp8
20035     # otherwise append
20036 $append-list:non-empty-list:
20037     # var curr/eax: (addr list _type) = lookup(list)
20038     (lookup *(ebp+0x14) *(ebp+0x18))  # => eax
20039     # while (curr->next != null) curr = curr->next
20040     {
20041       81 7/subop/compare *(eax+8) 0/imm32  # List-next
20042       74/jump-if-= break/disp8
20043       # curr = lookup(curr->next)
20044       (lookup *(eax+8) *(eax+0xc))  # List-next, List-next => eax
20045       #
20046       eb/jump loop/disp8
20047     }
20048     # edi = out
20049     8b/-> *(ebp+0x1c) 7/r32/edi
20050     # curr->next = out
20051     8b/-> *edi 1/r32/ecx
20052     89/<- *(eax+8) 1/r32/ecx  # List-next
20053     8b/-> *(edi+4) 1/r32/ecx
20054     89/<- *(eax+0xc) 1/r32/ecx  # List-next
20055     # out = list
20056     8b/-> *(ebp+0x14) 1/r32/ecx
20057     89/<- *edi 1/r32/ecx
20058     8b/-> *(ebp+0x18) 1/r32/ecx
20059     89/<- *(edi+4) 1/r32/ecx
20060 $append-list:end:
20061     # . restore registers
20062     5f/pop-to-edi
20063     59/pop-to-ecx
20064     58/pop-to-eax
20065     # . epilogue
20066     89/<- %esp 5/r32/ebp
20067     5d/pop-to-ebp
20068     c3/return
20069 
20070 append-stmt-var:  # ad: (addr allocation-descriptor), v: (handle var), vars: (handle stmt-var), is-deref?: boolean, out: (addr handle stmt-var)
20071     # . prologue
20072     55/push-ebp
20073     89/<- %ebp 4/r32/esp
20074     # . save registers
20075     50/push-eax
20076     51/push-ecx
20077     57/push-edi
20078     # edi = out
20079     8b/-> *(ebp+0x20) 7/r32/edi
20080     # out = new stmt-var
20081     (allocate *(ebp+8) *Stmt-var-size %edi)
20082     # var out-addr/ecx: (addr stmt-var) = lookup(*out)
20083     (lookup *edi *(edi+4))  # => eax
20084     89/<- %ecx 0/r32/eax
20085     # out-addr->value = v
20086     8b/-> *(ebp+0xc) 0/r32/eax
20087     89/<- *ecx 0/r32/eax  # Stmt-var-value
20088     8b/-> *(ebp+0x10) 0/r32/eax
20089     89/<- *(ecx+4) 0/r32/eax  # Stmt-var-value
20090     # out-addr->is-deref? = is-deref?
20091     8b/-> *(ebp+0x1c) 0/r32/eax
20092     89/<- *(ecx+0x10) 0/r32/eax  # Stmt-var-is-deref
20093     # if (vars == null) return result
20094     81 7/subop/compare *(ebp+0x14) 0/imm32/null
20095     74/jump-if-= $append-stmt-var:end/disp8
20096     # otherwise append
20097     # var curr/eax: (addr stmt-var) = lookup(vars)
20098     (lookup *(ebp+0x14) *(ebp+0x18))  # => eax
20099     # while (curr->next != null) curr = curr->next
20100     {
20101       81 7/subop/compare *(eax+8) 0/imm32  # Stmt-var-next
20102       74/jump-if-= break/disp8
20103       # curr = lookup(curr->next)
20104       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next, Stmt-var-next => eax
20105       #
20106       eb/jump loop/disp8
20107     }
20108     # curr->next = out
20109     8b/-> *edi 1/r32/ecx
20110     89/<- *(eax+8) 1/r32/ecx  # Stmt-var-next
20111     8b/-> *(edi+4) 1/r32/ecx
20112     89/<- *(eax+0xc) 1/r32/ecx  # Stmt-var-next
20113     # out = vars
20114     8b/-> *(ebp+0x14) 1/r32/ecx
20115     89/<- *edi 1/r32/ecx
20116     8b/-> *(ebp+0x18) 1/r32/ecx
20117     89/<- *(edi+4) 1/r32/ecx
20118 $append-stmt-var:end:
20119     # . restore registers
20120     5f/pop-to-edi
20121     59/pop-to-ecx
20122     58/pop-to-eax
20123     # . epilogue
20124     89/<- %esp 5/r32/ebp
20125     5d/pop-to-ebp
20126     c3/return
20127 
20128 append-to-block:  # ad: (addr allocation-descriptor), block: (addr block), x: (handle stmt)
20129     # . prologue
20130     55/push-ebp
20131     89/<- %ebp 4/r32/esp
20132     # . save registers
20133     50/push-eax
20134     56/push-esi
20135     # esi = block
20136     8b/-> *(ebp+0xc) 6/r32/esi
20137     # block->stmts = append(x, block->stmts)
20138     8d/copy-address *(esi+4) 0/r32/eax  # Block-stmts
20139     (append-list *(ebp+8)  *(ebp+0x10) *(ebp+0x14)  *(esi+4) *(esi+8)  %eax)  # ad, x, x, Block-stmts, Block-stmts
20140 $append-to-block:end:
20141     # . restore registers
20142     5e/pop-to-esi
20143     58/pop-to-eax
20144     # . epilogue
20145     89/<- %esp 5/r32/ebp
20146     5d/pop-to-ebp
20147     c3/return
20148 
20149 ## Parsing types
20150 # We need to create metadata on user-defined types, and we need to use this
20151 # metadata as we parse instructions.
20152 # However, we also want to allow types to be used before their definitions.
20153 # This means we can't ever assume any type data structures exist.
20154 
20155 lookup-or-create-constant:  # container: (addr stmt-var), field-name: (addr slice), out: (addr handle var)
20156     # . prologue
20157     55/push-ebp
20158     89/<- %ebp 4/r32/esp
20159     # . save registers
20160     50/push-eax
20161     56/push-esi
20162     # var container-type/esi: type-id
20163     (container-type *(ebp+8))  # => eax
20164     89/<- %esi 0/r32/eax
20165     # var tmp/eax: (handle typeinfo) = find-or-create-typeinfo(container-type)
20166     68/push 0/imm32
20167     68/push 0/imm32
20168     89/<- %eax 4/r32/esp
20169     (find-or-create-typeinfo %esi %eax)
20170     # var tmp-addr/eax: (addr typeinfo) = lookup(tmp)
20171     (lookup *eax *(eax+4))  # => eax
20172     # result = find-or-create-typeinfo-output-var(typeinfo, field-name)
20173 #?     (write-buffered Stderr "constant: ")
20174 #?     (write-slice-buffered Stderr *(ebp+0xc))
20175 #?     (write-buffered Stderr Newline)
20176 #?     (flush Stderr)
20177     (find-or-create-typeinfo-output-var %eax *(ebp+0xc) *(ebp+0x10))
20178 #?     8b/-> *(ebp+0x10) 0/r32/eax
20179 #?     (write-buffered Stderr "@")
20180 #?     (lookup *eax *(eax+4))
20181 #?     (write-int32-hex-buffered Stderr %eax)
20182 #?     (lookup *eax *(eax+4))
20183 #?     (write-buffered Stderr %eax)
20184 #?     (write-buffered Stderr Newline)
20185 #?     (flush Stderr)
20186 #?     (write-buffered Stderr "offset: ")
20187 #?     8b/-> *(eax+0x14) 0/r32/eax
20188 #?     (write-int32-hex-buffered Stderr %eax)
20189 #?     (write-buffered Stderr Newline)
20190 #?     (flush Stderr)
20191 $lookup-or-create-constant:end:
20192     # . reclaim locals
20193     81 0/subop/add %esp 8/imm32
20194     # . restore registers
20195     5e/pop-to-esi
20196     58/pop-to-eax
20197     # . epilogue
20198     89/<- %esp 5/r32/ebp
20199     5d/pop-to-ebp
20200     c3/return
20201 
20202 # if addr var:
20203 #   container->var->type->right->left->value
20204 # otherwise
20205 #   container->var->type->value
20206 container-type:  # container: (addr stmt-var) -> result/eax: type-id
20207     # . prologue
20208     55/push-ebp
20209     89/<- %ebp 4/r32/esp
20210     #
20211     8b/-> *(ebp+8) 0/r32/eax
20212     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
20213     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20214     {
20215       81 7/subop/compare *(eax+8) 0/imm32  # Type-tree-right
20216       74/jump-if-= break/disp8
20217       (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
20218       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
20219     }
20220     8b/-> *(eax+4) 0/r32/eax  # Type-tree-value
20221 $container-type:end:
20222     # . epilogue
20223     89/<- %esp 5/r32/ebp
20224     5d/pop-to-ebp
20225     c3/return
20226 
20227 container?:  # t: type-id -> result/eax: boolean
20228     # . prologue
20229     55/push-ebp
20230     89/<- %ebp 4/r32/esp
20231     #
20232     8b/-> *(ebp+8) 0/r32/eax
20233     c1/shift 4/subop/left %eax 2/imm8
20234     3b/compare 0/r32/eax *Primitive-type-ids
20235     0f 9d/set-if->= %al
20236     81 4/subop/and %eax 0xff/imm32
20237 $container?:end:
20238     # . epilogue
20239     89/<- %esp 5/r32/ebp
20240     5d/pop-to-ebp
20241     c3/return
20242 
20243 find-or-create-typeinfo:  # t: type-id, out: (addr handle typeinfo)
20244     # . prologue
20245     55/push-ebp
20246     89/<- %ebp 4/r32/esp
20247     # . save registers
20248     50/push-eax
20249     51/push-ecx
20250     52/push-edx
20251     57/push-edi
20252     # edi = out
20253     8b/-> *(ebp+0xc) 7/r32/edi
20254     # var fields/ecx: (handle table (handle array byte) (handle typeinfo-entry))
20255     68/push 0/imm32
20256     68/push 0/imm32
20257     89/<- %ecx 4/r32/esp
20258     # find-typeinfo(t, out)
20259     (find-typeinfo *(ebp+8) %edi)
20260     {
20261       # if (*out != 0) break
20262       81 7/subop/compare *edi 0/imm32
20263       0f 85/jump-if-!= break/disp32
20264 $find-or-create-typeinfo:create:
20265       # *out = allocate
20266       (allocate Heap *Typeinfo-size %edi)
20267       # var tmp/eax: (addr typeinfo) = lookup(*out)
20268       (lookup *edi *(edi+4))  # => eax
20269 #?     (write-buffered Stderr "created typeinfo at ")
20270 #?     (write-int32-hex-buffered Stderr %eax)
20271 #?     (write-buffered Stderr " for type-id ")
20272 #?     (write-int32-hex-buffered Stderr *(ebp+8))
20273 #?     (write-buffered Stderr Newline)
20274 #?     (flush Stderr)
20275       # tmp->id = t
20276       8b/-> *(ebp+8) 2/r32/edx
20277       89/<- *eax 2/r32/edx  # Typeinfo-id
20278       # tmp->fields = new table
20279       # . fields = new table
20280       (new-stream Heap 0x40 *Typeinfo-fields-row-size %ecx)
20281       # . tmp->fields = fields
20282       8b/-> *ecx 2/r32/edx
20283       89/<- *(eax+4) 2/r32/edx  # Typeinfo-fields
20284       8b/-> *(ecx+4) 2/r32/edx
20285       89/<- *(eax+8) 2/r32/edx  # Typeinfo-fields
20286       # tmp->next = Program->types
20287       8b/-> *_Program-types 1/r32/ecx
20288       89/<- *(eax+0x10) 1/r32/ecx  # Typeinfo-next
20289       8b/-> *_Program-types->payload 1/r32/ecx
20290       89/<- *(eax+0x14) 1/r32/ecx  # Typeinfo-next
20291       # Program->types = out
20292       8b/-> *edi 1/r32/ecx
20293       89/<- *_Program-types 1/r32/ecx
20294       8b/-> *(edi+4) 1/r32/ecx
20295       89/<- *_Program-types->payload 1/r32/ecx
20296     }
20297 $find-or-create-typeinfo:end:
20298     # . reclaim locals
20299     81 0/subop/add %esp 8/imm32
20300     # . restore registers
20301     5f/pop-to-edi
20302     5a/pop-to-edx
20303     59/pop-to-ecx
20304     58/pop-to-eax
20305     # . epilogue
20306     89/<- %esp 5/r32/ebp
20307     5d/pop-to-ebp
20308     c3/return
20309 
20310 find-typeinfo:  # t: type-id, out: (addr handle typeinfo)
20311     # . prologue
20312     55/push-ebp
20313     89/<- %ebp 4/r32/esp
20314     # . save registers
20315     50/push-eax
20316     51/push-ecx
20317     52/push-edx
20318     57/push-edi
20319     # ecx = t
20320     8b/-> *(ebp+8) 1/r32/ecx
20321     # edi = out
20322     8b/-> *(ebp+0xc) 7/r32/edi
20323     # *out = Program->types
20324     8b/-> *_Program-types 0/r32/eax
20325     89/<- *edi 0/r32/eax
20326     8b/-> *_Program-types->payload 0/r32/eax
20327     89/<- *(edi+4) 0/r32/eax
20328     {
20329 $find-typeinfo:loop:
20330       # if (*out == 0) break
20331       81 7/subop/compare *edi 0/imm32
20332       74/jump-if-= break/disp8
20333 $find-typeinfo:check:
20334       # var tmp/eax: (addr typeinfo) = lookup(*out)
20335       (lookup *edi *(edi+4))  # => eax
20336       # if (tmp->id == t) break
20337       39/compare *eax 1/r32/ecx  # Typeinfo-id
20338       74/jump-if-= break/disp8
20339 $find-typeinfo:continue:
20340       # *out = tmp->next
20341       8b/-> *(eax+0x10) 2/r32/edx  # Typeinfo-next
20342       89/<- *edi 2/r32/edx
20343       8b/-> *(eax+0x14) 2/r32/edx  # Typeinfo-next
20344       89/<- *(edi+4) 2/r32/edx
20345       #
20346       eb/jump loop/disp8
20347     }
20348 $find-typeinfo:end:
20349     # . restore registers
20350     5f/pop-to-edi
20351     5a/pop-to-edx
20352     59/pop-to-ecx
20353     58/pop-to-eax
20354     # . epilogue
20355     89/<- %esp 5/r32/ebp
20356     5d/pop-to-ebp
20357     c3/return
20358 
20359 find-or-create-typeinfo-output-var:  # T: (addr typeinfo), f: (addr slice), out: (addr handle var)
20360     # . prologue
20361     55/push-ebp
20362     89/<- %ebp 4/r32/esp
20363     # . save registers
20364     50/push-eax
20365     52/push-edx
20366     57/push-edi
20367     # var dest/edi: (handle typeinfo-entry)
20368     68/push 0/imm32
20369     68/push 0/imm32
20370     89/<- %edi 4/r32/esp
20371     # find-or-create-typeinfo-fields(T, f, dest)
20372     (find-or-create-typeinfo-fields *(ebp+8) *(ebp+0xc) %edi)
20373     # var dest-addr/edi: (addr typeinfo-entry) = lookup(dest)
20374     (lookup *edi *(edi+4))  # => eax
20375     89/<- %edi 0/r32/eax
20376     # if dest-addr->output-var doesn't exist, create it
20377     {
20378       81 7/subop/compare *(edi+0xc) 0/imm32  # Typeinfo-entry-output-var
20379       0f 85/jump-if-!= break/disp32
20380       # dest-addr->output-var = new var(dummy name, type, -1 offset)
20381       # . var name/eax: (handle array byte) = "field"
20382       68/push 0/imm32
20383       68/push 0/imm32
20384       89/<- %eax 4/r32/esp
20385       (slice-to-string Heap *(ebp+0xc) %eax)
20386       # . new var
20387       8d/copy-address *(edi+0xc) 2/r32/edx
20388       (new-var Heap  *eax *(eax+4)  %edx)
20389       # . reclaim name
20390       81 0/subop/add %esp 8/imm32
20391       # var result/edx: (addr var) = lookup(dest-addr->output-var)
20392       (lookup *(edi+0xc) *(edi+0x10))  # => eax
20393       89/<- %edx 0/r32/eax
20394       # result->type = new constant type
20395       8d/copy-address *(edx+8) 0/r32/eax  # Var-type
20396       (allocate Heap *Type-tree-size %eax)
20397       (lookup *(edx+8) *(edx+0xc))  # => eax
20398       c7 0/subop/copy *eax 1/imm32/true  # Type-tree-is-atom
20399       c7 0/subop/copy *(eax+4) 6/imm32/constant  # Type-tree-value
20400       c7 0/subop/copy *(eax+8) 0/imm32  # Type-tree-left
20401       c7 0/subop/copy *(eax+0xc) 0/imm32  # Type-tree-right
20402       c7 0/subop/copy *(eax+0x10) 0/imm32  # Type-tree-right
20403       # result->offset isn't filled out yet
20404       c7 0/subop/copy *(edx+0x14) -1/imm32/uninitialized  # Var-offset
20405     }
20406     # out = dest-addr->output-var
20407     8b/-> *(ebp+0x10) 2/r32/edx
20408     8b/-> *(edi+0xc) 0/r32/eax  # Typeinfo-entry-output-var
20409     89/<- *edx 0/r32/eax
20410     8b/-> *(edi+0x10) 0/r32/eax  # Typeinfo-entry-output-var
20411     89/<- *(edx+4) 0/r32/eax
20412 $find-or-create-typeinfo-output-var:end:
20413     # . reclaim locals
20414     81 0/subop/add %esp 8/imm32
20415     # . restore registers
20416     5f/pop-to-edi
20417     5a/pop-to-edx
20418     58/pop-to-eax
20419     # . epilogue
20420     89/<- %esp 5/r32/ebp
20421     5d/pop-to-ebp
20422     c3/return
20423 
20424 find-or-create-typeinfo-fields:  # T: (addr typeinfo), f: (addr slice), out: (addr handle typeinfo-entry)
20425     # . prologue
20426     55/push-ebp
20427     89/<- %ebp 4/r32/esp
20428     # . save registers
20429     50/push-eax
20430     56/push-esi
20431     57/push-edi
20432     # eax = lookup(T->fields)
20433     8b/-> *(ebp+8) 0/r32/eax
20434     (lookup *(eax+4) *(eax+8))  # Typeinfo-fields Typeinfo-fields => eax
20435     # edi = out
20436     8b/-> *(ebp+0x10) 7/r32/edi
20437     # var src/esi: (addr handle typeinfo-entry) = get-or-insert-slice(T->fields, f)
20438     (get-or-insert-slice %eax *(ebp+0xc) *Typeinfo-fields-row-size Heap)  # => eax
20439     89/<- %esi 0/r32/eax
20440     # if src doesn't exist, allocate it
20441     {
20442       81 7/subop/compare *esi 0/imm32
20443       75/jump-if-!= break/disp8
20444       (allocate Heap *Typeinfo-entry-size %esi)
20445 #?       (write-buffered Stderr "handle at ")
20446 #?       (write-int32-hex-buffered Stderr %esi)
20447 #?       (write-buffered Stderr ": ")
20448 #?       (write-int32-hex-buffered Stderr *esi)
20449 #?       (write-buffered Stderr " ")
20450 #?       (write-int32-hex-buffered Stderr *(esi+4))
20451 #?       (write-buffered Stderr Newline)
20452 #?       (flush Stderr)
20453 #?       (lookup *esi *(esi+4))
20454 #?       (write-buffered Stderr "created typeinfo fields at ")
20455 #?       (write-int32-hex-buffered Stderr %esi)
20456 #?       (write-buffered Stderr " for ")
20457 #?       (write-int32-hex-buffered Stderr *(ebp+8))
20458 #?       (write-buffered Stderr Newline)
20459 #?       (flush Stderr)
20460     }
20461     # *out = src
20462     # . *edi = *src
20463     8b/-> *esi 0/r32/eax
20464     89/<- *edi 0/r32/eax
20465     8b/-> *(esi+4) 0/r32/eax
20466     89/<- *(edi+4) 0/r32/eax
20467 $find-or-create-typeinfo-fields:end:
20468     # . restore registers
20469     5f/pop-to-edi
20470     5e/pop-to-esi
20471     58/pop-to-eax
20472     # . epilogue
20473     89/<- %esp 5/r32/ebp
20474     5d/pop-to-ebp
20475     c3/return
20476 
20477 populate-mu-type:  # in: (addr stream byte), t: (addr typeinfo), err: (addr buffered-file), ed: (addr exit-descriptor)
20478     # pseudocode:
20479     #   var line: (stream byte 512)
20480     #   curr-index = 0
20481     #   while true
20482     #     clear-stream(line)
20483     #     read-line-buffered(in, line)
20484     #     if line->write == 0
20485     #       abort
20486     #     word-slice = next-mu-token(line)
20487     #     if slice-empty?(word-slice)               # end of line
20488     #       continue
20489     #     if slice-equal?(word-slice, "}")
20490     #       break
20491     #     var v: (handle var) = parse-var-with-type(word-slice, line)
20492     #     var r: (handle typeinfo-fields) = find-or-create-typeinfo-fields(t, word-slice/v->name)
20493     #     TODO: ensure that r->first is null
20494     #     r->index = curr-index
20495     #     curr-index++
20496     #     r->input-var = v
20497     #     if r->output-var == 0
20498     #       r->output-var = new literal
20499     #     TODO: ensure nothing else in line
20500     # t->total-size-in-bytes = -2 (not yet initialized)
20501     #
20502     # . prologue
20503     55/push-ebp
20504     89/<- %ebp 4/r32/esp
20505     # var curr-index: int at *(ebp-4)
20506     68/push 0/imm32
20507     # . save registers
20508     50/push-eax
20509     51/push-ecx
20510     52/push-edx
20511     53/push-ebx
20512     56/push-esi
20513     57/push-edi
20514     # edi = t
20515     8b/-> *(ebp+0xc) 7/r32/edi
20516     # var line/ecx: (stream byte 512)
20517     81 5/subop/subtract %esp 0x200/imm32
20518     68/push 0x200/imm32/size
20519     68/push 0/imm32/read
20520     68/push 0/imm32/write
20521     89/<- %ecx 4/r32/esp
20522     # var word-slice/edx: slice
20523     68/push 0/imm32/end
20524     68/push 0/imm32/start
20525     89/<- %edx 4/r32/esp
20526     # var v/esi: (handle var)
20527     68/push 0/imm32
20528     68/push 0/imm32
20529     89/<- %esi 4/r32/esp
20530     # var r/ebx: (handle typeinfo-entry)
20531     68/push 0/imm32
20532     68/push 0/imm32
20533     89/<- %ebx 4/r32/esp
20534     {
20535 $populate-mu-type:line-loop:
20536       (clear-stream %ecx)
20537       (read-line-buffered *(ebp+8) %ecx)
20538       # if (line->write == 0) abort
20539       81 7/subop/compare *ecx 0/imm32
20540       0f 84/jump-if-= $populate-mu-type:error1/disp32
20541 +--  6 lines: #?       # dump line ------------------------------------------------------------------------------------------------------------------------------------------------------
20547       (next-mu-token %ecx %edx)
20548       # if slice-empty?(word-slice) continue
20549       (slice-empty? %edx)  # => eax
20550       3d/compare-eax-and 0/imm32
20551       0f 85/jump-if-!= loop/disp32
20552       # if slice-equal?(word-slice, "}") break
20553       (slice-equal? %edx "}")
20554       3d/compare-eax-and 0/imm32
20555       0f 85/jump-if-!= break/disp32
20556 $populate-mu-type:parse-element:
20557       # v = parse-var-with-type(word-slice, first-line)
20558       # must do this first to strip the trailing ':' from word-slice before
20559       # using it in find-or-create-typeinfo-fields below
20560       # TODO: clean up that mutation in parse-var-with-type
20561       (type-name *edi)  # Typeinfo-id => eax
20562       (parse-var-with-type %edx %ecx %esi %eax *(ebp+0x10) *(ebp+0x14))
20563       # if v is an addr, abort
20564       (lookup *esi *(esi+4))  # => eax
20565       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20566       (mu-addr-type? %eax)  # => eax
20567       3d/compare-eax-and 0/imm32/false
20568       0f 85/jump-if-!= $populate-mu-type:error2/disp32
20569       # if v is an array, abort  (we could support it, but initialization gets complex)
20570       (lookup *esi *(esi+4))  # => eax
20571       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20572       (mu-array-type? %eax)  # => eax
20573       3d/compare-eax-and 0/imm32/false
20574       0f 85/jump-if-!= $populate-mu-type:error3/disp32
20575       # if v is a byte, abort
20576       (lookup *esi *(esi+4))  # => eax
20577       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20578       (simple-mu-type? %eax 8)  # byte => eax
20579       3d/compare-eax-and 0/imm32/false
20580       0f 85/jump-if-!= $populate-mu-type:error4/disp32
20581       # if v is a slice, abort
20582       (lookup *esi *(esi+4))  # => eax
20583       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20584       (simple-mu-type? %eax 0xc)  # slice => eax
20585       3d/compare-eax-and 0/imm32/false
20586       0f 85/jump-if-!= $populate-mu-type:error5/disp32
20587       # if v is a stream, abort  (we could support it, but initialization gets even more complex)
20588       (lookup *esi *(esi+4))  # => eax
20589       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20590       (mu-stream-type? %eax)  # => eax
20591       3d/compare-eax-and 0/imm32/false
20592       0f 85/jump-if-!= $populate-mu-type:error6/disp32
20593       # var tmp/ecx
20594       51/push-ecx
20595 $populate-mu-type:create-typeinfo-fields:
20596       # var r/ebx: (handle typeinfo-entry)
20597       (find-or-create-typeinfo-fields %edi %edx %ebx)
20598       # r->index = curr-index
20599       (lookup *ebx *(ebx+4))  # => eax
20600       8b/-> *(ebp-4) 1/r32/ecx
20601 #?       (write-buffered Stderr "saving index ")
20602 #?       (write-int32-hex-buffered Stderr %ecx)
20603 #?       (write-buffered Stderr " at ")
20604 #?       (write-int32-hex-buffered Stderr %edi)
20605 #?       (write-buffered Stderr Newline)
20606 #?       (flush Stderr)
20607       89/<- *(eax+8) 1/r32/ecx  # Typeinfo-entry-index
20608       # ++curr-index
20609       ff 0/subop/increment *(ebp-4)
20610 $populate-mu-type:set-input-type:
20611       # r->input-var = v
20612       8b/-> *esi 1/r32/ecx
20613       89/<- *eax 1/r32/ecx  # Typeinfo-entry-input-var
20614       8b/-> *(esi+4) 1/r32/ecx
20615       89/<- *(eax+4) 1/r32/ecx  # Typeinfo-entry-input-var
20616       # restore line
20617       59/pop-to-ecx
20618       {
20619 $populate-mu-type:create-output-type:
20620         # if (r->output-var == 0) create a new var with some placeholder data
20621         81 7/subop/compare *(eax+0xc) 0/imm32  # Typeinfo-entry-output-var
20622         75/jump-if-!= break/disp8
20623         8d/copy-address *(eax+0xc) 0/r32/eax  # Typeinfo-entry-output-var
20624         (new-literal Heap %edx %eax)
20625       }
20626       e9/jump loop/disp32
20627     }
20628 $populate-mu-type:invalidate-total-size-in-bytes:
20629     # Offsets and total size may not be accurate here since we may not yet
20630     # have encountered the element types.
20631     # We'll recompute them separately after parsing the entire program.
20632     c7 0/subop/copy *(edi+0xc) -2/imm32/uninitialized  # Typeinfo-total-size-in-bytes
20633 $populate-mu-type:end:
20634     # . reclaim locals
20635     81 0/subop/add %esp 0x224/imm32
20636     # . restore registers
20637     5f/pop-to-edi
20638     5e/pop-to-esi
20639     5b/pop-to-ebx
20640     5a/pop-to-edx
20641     59/pop-to-ecx
20642     58/pop-to-eax
20643     # reclaim curr-index
20644     81 0/subop/add %esp 4/imm32
20645     # . epilogue
20646     89/<- %esp 5/r32/ebp
20647     5d/pop-to-ebp
20648     c3/return
20649 
20650 $populate-mu-type:error1:
20651     # error("incomplete type definition '" t->name "'\n")
20652     (write-buffered *(ebp+0x10) "incomplete type definition '")
20653     (type-name *edi)  # Typeinfo-id => eax
20654     (write-buffered *(ebp+0x10) %eax)
20655     (write-buffered *(ebp+0x10) "\n")
20656     (flush *(ebp+0x10))
20657     (stop *(ebp+0x14) 1)
20658     # never gets here
20659 
20660 $populate-mu-type:error2:
20661     (write-buffered *(ebp+0x10) "type ")
20662     (type-name *edi)  # Typeinfo-id => eax
20663     (write-buffered *(ebp+0x10) %eax)
20664     (write-buffered *(ebp+0x10) ": 'addr' elements not allowed\n")
20665     (flush *(ebp+0x10))
20666     (stop *(ebp+0x14) 1)
20667     # never gets here
20668 
20669 $populate-mu-type:error3:
20670     (write-buffered *(ebp+0x10) "type ")
20671     (type-name *edi)  # Typeinfo-id => eax
20672     (write-buffered *(ebp+0x10) %eax)
20673     (write-buffered *(ebp+0x10) ": 'array' elements not allowed for now\n")
20674     (flush *(ebp+0x10))
20675     (stop *(ebp+0x14) 1)
20676     # never gets here
20677 
20678 $populate-mu-type:error4:
20679     (write-buffered *(ebp+0x10) "type ")
20680     (type-name *edi)  # Typeinfo-id => eax
20681     (write-buffered *(ebp+0x10) %eax)
20682     (write-buffered *(ebp+0x10) ": 'byte' elements not allowed\n")
20683     (flush *(ebp+0x10))
20684     (stop *(ebp+0x14) 1)
20685     # never gets here
20686 
20687 $populate-mu-type:error5:
20688     (write-buffered *(ebp+0x10) "type ")
20689     (type-name *edi)  # Typeinfo-id => eax
20690     (write-buffered *(ebp+0x10) %eax)
20691     (write-buffered *(ebp+0x10) ": 'slice' elements not allowed\n")
20692     (flush *(ebp+0x10))
20693     (stop *(ebp+0x14) 1)
20694     # never gets here
20695 
20696 $populate-mu-type:error6:
20697     (write-buffered *(ebp+0x10) "type ")
20698     (type-name *edi)  # Typeinfo-id => eax
20699     (write-buffered *(ebp+0x10) %eax)
20700     (write-buffered *(ebp+0x10) ": 'stream' elements not allowed for now\n")
20701     (flush *(ebp+0x10))
20702     (stop *(ebp+0x14) 1)
20703     # never gets here
20704 
20705 type-name:  # index: int -> result/eax: (addr array byte)
20706     # . prologue
20707     55/push-ebp
20708     89/<- %ebp 4/r32/esp
20709     #
20710     (index Type-id *(ebp+8))
20711 $type-name:end:
20712     # . epilogue
20713     89/<- %esp 5/r32/ebp
20714     5d/pop-to-ebp
20715     c3/return
20716 
20717 index:  # arr: (addr stream (handle array byte)), index: int -> result/eax: (addr array byte)
20718     # . prologue
20719     55/push-ebp
20720     89/<- %ebp 4/r32/esp
20721     # . save registers
20722     56/push-esi
20723     # TODO: bounds-check index
20724     # esi = arr
20725     8b/-> *(ebp+8) 6/r32/esi
20726     # eax = index
20727     8b/-> *(ebp+0xc) 0/r32/eax
20728     # eax = *(arr + 12 + index)
20729     8b/-> *(esi+eax<<2+0xc) 0/r32/eax
20730 $index:end:
20731     # . restore registers
20732     5e/pop-to-esi
20733     # . epilogue
20734     89/<- %esp 5/r32/ebp
20735     5d/pop-to-ebp
20736     c3/return
20737 
20738 #######################################################
20739 # Compute type sizes
20740 #######################################################
20741 
20742 # Compute the sizes of all user-defined types.
20743 # We'll need the sizes of their elements, which may be other user-defined
20744 # types, which we will compute as needed.
20745 
20746 # Initially, all user-defined types have their sizes set to -2 (invalid)
20747 populate-mu-type-sizes:  # err: (addr buffered-file), ed: (addr exit-descriptor)
20748     # . prologue
20749     55/push-ebp
20750     89/<- %ebp 4/r32/esp
20751 $populate-mu-type-sizes:total-sizes:
20752     # var curr/eax: (addr typeinfo) = lookup(Program->types)
20753     (lookup *_Program-types *_Program-types->payload)  # => eax
20754     {
20755       # if (curr == null) break
20756       3d/compare-eax-and 0/imm32/null
20757       74/jump-if-= break/disp8
20758       (populate-mu-type-sizes-in-type %eax *(ebp+8) *(ebp+0xc))
20759       # curr = lookup(curr->next)
20760       (lookup *(eax+0x10) *(eax+0x14))  # Typeinfo-next Typeinfo-next => eax
20761       eb/jump loop/disp8
20762     }
20763 $populate-mu-type-sizes:offsets:
20764     # curr = *Program->types
20765     (lookup *_Program-types *_Program-types->payload)  # => eax
20766     {
20767       # if (curr == null) break
20768       3d/compare-eax-and 0/imm32/null
20769       74/jump-if-= break/disp8
20770       (populate-mu-type-offsets %eax *(ebp+8) *(ebp+0xc))
20771       # curr = curr->next
20772       (lookup *(eax+0x10) *(eax+0x14))  # Typeinfo-next Typeinfo-next => eax
20773       eb/jump loop/disp8
20774     }
20775 $populate-mu-type-sizes:end:
20776     # . epilogue
20777     89/<- %esp 5/r32/ebp
20778     5d/pop-to-ebp
20779     c3/return
20780 
20781 # compute sizes of all fields, recursing as necessary
20782 # sum up all their sizes to arrive at total size
20783 # fields may be out of order, but that doesn't affect the answer
20784 populate-mu-type-sizes-in-type:  # T: (addr typeinfo), err: (addr buffered-file), ed: (addr exit-descriptor)
20785     # . prologue
20786     55/push-ebp
20787     89/<- %ebp 4/r32/esp
20788     # . save registers
20789     50/push-eax
20790     51/push-ecx
20791     52/push-edx
20792     56/push-esi
20793     57/push-edi
20794     # esi = T
20795     8b/-> *(ebp+8) 6/r32/esi
20796     # if T is already computed, return
20797     81 7/subop/compare *(esi+0xc) 0/imm32  # Typeinfo-total-size-in-bytes
20798     0f 8d/jump-if->= $populate-mu-type-sizes-in-type:end/disp32
20799     # if T is being computed, abort
20800     81 7/subop/compare *(esi+0xc) -1/imm32/being-computed  # Typeinfo-total-size-in-bytes
20801     0f 84/jump-if-= $populate-mu-type-sizes-in-type:abort/disp32
20802     # tag T (-2 to -1) to avoid infinite recursion
20803     c7 0/subop/copy *(esi+0xc) -1/imm32/being-computed  # Typeinfo-total-size-in-bytes
20804     # var total-size/edi: int = 0
20805     bf/copy-to-edi 0/imm32
20806     # - for every field, if it's a user-defined type, compute its size
20807     # var table/ecx: (addr table (handle array byte) (handle typeinfo-entry)) = lookup(T->fields)
20808     (lookup *(esi+4) *(esi+8))  # Typeinfo-fields Typeinfo-fields => eax
20809     89/<- %ecx 0/r32/eax
20810     # var table-size/edx: int = table->write
20811     8b/-> *ecx 2/r32/edx  # stream-write
20812     # var curr/ecx: (addr table_row) = table->data
20813     8d/copy-address *(ecx+0xc) 1/r32/ecx
20814     # var max/edx: (addr table_row) = table->data + table->write
20815     8d/copy-address *(ecx+edx) 2/r32/edx
20816     {
20817 $populate-mu-type-sizes-in-type:loop:
20818       # if (curr >= max) break
20819       39/compare %ecx 2/r32/edx
20820       73/jump-if-addr>= break/disp8
20821       # var t/eax: (addr typeinfo-entry) = lookup(curr->value)
20822       (lookup *(ecx+8) *(ecx+0xc))  # => eax
20823       # if (t->input-var == 0) silently ignore it; we'll emit a nice error message while type-checking
20824       81 7/subop/compare *eax 0/imm32  # Typeinfo-entry-input-var
20825       74/jump-if-= $populate-mu-type-sizes-in-type:end/disp8
20826       # compute size of t->input-var
20827       (lookup *eax *(eax+4))  # Typeinfo-entry-input-var Typeinfo-entry-input-var => eax
20828       (compute-size-of-var %eax *(ebp+0xc) *(ebp+0x10))  # => eax
20829       # result += eax
20830       01/add-to %edi 0/r32/eax
20831       # curr += row-size
20832       81 0/subop/add %ecx 0x10/imm32  # Typeinfo-fields-row-size
20833       #
20834       eb/jump loop/disp8
20835     }
20836     # - save result
20837     89/<- *(esi+0xc) 7/r32/edi  # Typeinfo-total-size-in-bytes
20838 $populate-mu-type-sizes-in-type:end:
20839     # . restore registers
20840     5f/pop-to-edi
20841     5e/pop-to-esi
20842     5a/pop-to-edx
20843     59/pop-to-ecx
20844     58/pop-to-eax
20845     # . epilogue
20846     89/<- %esp 5/r32/ebp
20847     5d/pop-to-ebp
20848     c3/return
20849 
20850 $populate-mu-type-sizes-in-type:abort:
20851     (write-buffered *(ebp+0xc) "cycle in type definitions\n")
20852     (flush *(ebp+0xc))
20853     (stop *(ebp+0x10) 1)
20854     # never gets here
20855 
20856 # Analogous to size-of, except we need to compute what size-of can just read
20857 # off the right data structures.
20858 compute-size-of-var:  # in: (addr var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
20859     # . prologue
20860     55/push-ebp
20861     89/<- %ebp 4/r32/esp
20862     # . push registers
20863     51/push-ecx
20864     # var t/ecx: (addr type-tree) = lookup(v->type)
20865     8b/-> *(ebp+8) 1/r32/ecx
20866     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
20867     89/<- %ecx 0/r32/eax
20868     # if (t->is-atom == false) t = lookup(t->left)
20869     {
20870       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
20871       75/jump-if-!= break/disp8
20872       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
20873       89/<- %ecx 0/r32/eax
20874     }
20875     # TODO: ensure t is an atom
20876     (compute-size-of-type-id *(ecx+4) *(ebp+0xc) *(ebp+0x10))  # Type-tree-value => eax
20877 $compute-size-of-var:end:
20878     # . restore registers
20879     59/pop-to-ecx
20880     # . epilogue
20881     89/<- %esp 5/r32/ebp
20882     5d/pop-to-ebp
20883     c3/return
20884 
20885 compute-size-of-type-id:  # t: type-id, err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
20886     # . prologue
20887     55/push-ebp
20888     89/<- %ebp 4/r32/esp
20889     # . save registers
20890     51/push-ecx
20891     # var out/ecx: (handle typeinfo)
20892     68/push 0/imm32
20893     68/push 0/imm32
20894     89/<- %ecx 4/r32/esp
20895     # eax = t
20896     8b/-> *(ebp+8) 0/r32/eax
20897     # if t is a literal, return 0
20898     3d/compare-eax-and 0/imm32/literal
20899     0f 84/jump-if-= $compute-size-of-type-id:end/disp32  # eax changes type from type-id to int
20900     # if t is a byte, return 4 (because we don't really support non-multiples of 4)
20901     3d/compare-eax-and 8/imm32/byte
20902     {
20903       75/jump-if-!= break/disp8
20904       b8/copy-to-eax 4/imm32
20905       eb/jump $compute-size-of-type-id:end/disp8
20906     }
20907     # if t is a handle, return 8
20908     3d/compare-eax-and 4/imm32/handle
20909     {
20910       75/jump-if-!= break/disp8
20911       b8/copy-to-eax 8/imm32
20912       eb/jump $compute-size-of-type-id:end/disp8  # eax changes type from type-id to int
20913     }
20914     # if t is a slice, return 8
20915     3d/compare-eax-and 0xc/imm32/slice
20916     {
20917       75/jump-if-!= break/disp8
20918       b8/copy-to-eax 8/imm32
20919       eb/jump $compute-size-of-type-id:end/disp8  # eax changes type from type-id to int
20920     }
20921     # if t is a user-defined type, compute its size
20922     # TODO: support non-atom type
20923     (find-typeinfo %eax %ecx)
20924     {
20925       81 7/subop/compare *ecx 0/imm32
20926       74/jump-if-= break/disp8
20927 $compute-size-of-type-id:user-defined:
20928       (lookup *ecx *(ecx+4))  # => eax
20929       (populate-mu-type-sizes-in-type %eax *(ebp+0xc) *(ebp+0x10))
20930       8b/-> *(eax+0xc) 0/r32/eax  # Typeinfo-total-size-in-bytes
20931       eb/jump $compute-size-of-type-id:end/disp8
20932     }
20933     # otherwise return the word size
20934     b8/copy-to-eax 4/imm32
20935 $compute-size-of-type-id:end:
20936     # . reclaim locals
20937     81 0/subop/add %esp 8/imm32
20938     # . restore registers
20939     59/pop-to-ecx
20940     # . epilogue
20941     89/<- %esp 5/r32/ebp
20942     5d/pop-to-ebp
20943     c3/return
20944 
20945 # at this point we have total sizes for all user-defined types
20946 # compute offsets for each element
20947 # complication: fields may be out of order
20948 populate-mu-type-offsets:  # in: (addr typeinfo), err: (addr buffered-file), ed: (addr exit-descriptor)
20949     # . prologue
20950     55/push-ebp
20951     89/<- %ebp 4/r32/esp
20952     # . save registers
20953     50/push-eax
20954     51/push-ecx
20955     52/push-edx
20956     53/push-ebx
20957     56/push-esi
20958     57/push-edi
20959 #?     (dump-typeinfos "aaa\n")
20960     # var curr-offset/edi: int = 0
20961     bf/copy-to-edi 0/imm32
20962     # var table/ecx: (addr table string_key (handle typeinfo-entry)) = lookup(in->fields)
20963     8b/-> *(ebp+8) 1/r32/ecx
20964     (lookup *(ecx+4) *(ecx+8))  # Typeinfo-fields Typeinfo-fields => eax
20965     89/<- %ecx 0/r32/eax
20966     # var num-elems/edx: int = table->write / Typeinfo-fields-row-size
20967     8b/-> *ecx 2/r32/edx  # stream-write
20968     c1 5/subop/shift-right-logical  %edx 4/imm8
20969     # var i/ebx: int = 0
20970     bb/copy-to-ebx 0/imm32
20971     {
20972 $populate-mu-type-offsets:loop:
20973       39/compare %ebx 2/r32/edx
20974       0f 8d/jump-if->= break/disp32
20975 #?       (write-buffered Stderr "looking up index ")
20976 #?       (write-int32-hex-buffered Stderr %ebx)
20977 #?       (write-buffered Stderr " in ")
20978 #?       (write-int32-hex-buffered Stderr *(ebp+8))
20979 #?       (write-buffered Stderr Newline)
20980 #?       (flush Stderr)
20981       # var v/esi: (addr typeinfo-entry)
20982       (locate-typeinfo-entry-with-index %ecx %ebx *(ebp+0xc) *(ebp+0x10))  # => eax
20983       89/<- %esi 0/r32/eax
20984       # if v is null, silently move on; we'll emit a nice error message while type-checking
20985       81 7/subop/compare %esi 0/imm32  # Typeinfo-entry-input-var
20986       74/jump-if-= $populate-mu-type-offsets:end/disp8
20987       # if (v->input-var == 0) silently ignore v; we'll emit a nice error message while type-checking
20988       81 7/subop/compare *esi 0/imm32  # Typeinfo-entry-input-var
20989       74/jump-if-= $populate-mu-type-offsets:end/disp8
20990       # v->output-var->offset = curr-offset
20991       # . eax: (addr var)
20992       (lookup *(esi+0xc) *(esi+0x10))  # Typeinfo-entry-output-var Typeinfo-entry-output-var => eax
20993       89/<- *(eax+0x14) 7/r32/edi  # Var-offset
20994       # curr-offset += size-of(v->input-var)
20995       (lookup *esi *(esi+4))  # Typeinfo-entry-input-var Typeinfo-entry-input-var => eax
20996       (size-of %eax)  # => eax
20997       01/add-to %edi 0/r32/eax
20998       # ++i
20999       43/increment-ebx
21000       e9/jump loop/disp32
21001     }
21002 $populate-mu-type-offsets:end:
21003     # . restore registers
21004     5f/pop-to-edi
21005     5e/pop-to-esi
21006     5b/pop-to-ebx
21007     5a/pop-to-edx
21008     59/pop-to-ecx
21009     58/pop-to-eax
21010     # . epilogue
21011     89/<- %esp 5/r32/ebp
21012     5d/pop-to-ebp
21013     c3/return
21014 
21015 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)
21016     # . prologue
21017     55/push-ebp
21018     89/<- %ebp 4/r32/esp
21019     # . save registers
21020     51/push-ecx
21021     52/push-edx
21022     53/push-ebx
21023     56/push-esi
21024     57/push-edi
21025     # esi = table
21026     8b/-> *(ebp+8) 6/r32/esi
21027     # var curr/ecx: (addr row (handle array byte) (handle typeinfo-entry)) = table->data
21028     8d/copy-address *(esi+0xc) 1/r32/ecx
21029     # var max/edx: (addr byte) = &table->data[table->write]
21030     8b/-> *esi 2/r32/edx
21031     8d/copy-address *(ecx+edx) 2/r32/edx
21032     {
21033 $locate-typeinfo-entry-with-index:loop:
21034       39/compare %ecx 2/r32/edx
21035       73/jump-if-addr>= break/disp8
21036       # var v/eax: (addr typeinfo-entry)
21037       (lookup *(ecx+8) *(ecx+0xc))  # => eax
21038       # if (v->index == idx) return v
21039       8b/-> *(eax+8) 3/r32/ebx  # Typeinfo-entry-index
21040 #?       (write-buffered Stderr "comparing ")
21041 #?       (write-int32-hex-buffered Stderr %ebx)
21042 #?       (write-buffered Stderr " and ")
21043 #?       (write-int32-hex-buffered Stderr *(ebp+0xc))
21044 #?       (write-buffered Stderr Newline)
21045 #?       (flush Stderr)
21046       39/compare *(ebp+0xc) 3/r32/ebx
21047       74/jump-if-= $locate-typeinfo-entry-with-index:end/disp8
21048       # curr += Typeinfo-entry-size
21049       81 0/subop/add %ecx 0x10/imm32  # Typeinfo-entry-size
21050       #
21051       eb/jump loop/disp8
21052     }
21053     # return 0
21054     b8/copy-to-eax 0/imm32
21055 $locate-typeinfo-entry-with-index:end:
21056 #?     (write-buffered Stderr "returning ")
21057 #?     (write-int32-hex-buffered Stderr %eax)
21058 #?     (write-buffered Stderr Newline)
21059 #?     (flush Stderr)
21060     # . restore registers
21061     5f/pop-to-edi
21062     5e/pop-to-esi
21063     5b/pop-to-ebx
21064     5a/pop-to-edx
21065     59/pop-to-ecx
21066     # . epilogue
21067     89/<- %esp 5/r32/ebp
21068     5d/pop-to-ebp
21069     c3/return
21070 
21071 dump-typeinfos:  # hdr: (addr array byte)
21072     # . prologue
21073     55/push-ebp
21074     89/<- %ebp 4/r32/esp
21075     # . save registers
21076     50/push-eax
21077     #
21078     (write-buffered Stderr *(ebp+8))
21079     (flush Stderr)
21080     # var curr/eax: (addr typeinfo) = lookup(Program->types)
21081     (lookup *_Program-types *_Program-types->payload)  # => eax
21082     {
21083       # if (curr == null) break
21084       3d/compare-eax-and 0/imm32
21085       74/jump-if-= break/disp8
21086       (write-buffered Stderr "---\n")
21087       (flush Stderr)
21088       (dump-typeinfo %eax)
21089       # curr = lookup(curr->next)
21090       (lookup *(eax+0x10) *(eax+0x14))  # Typeinfo-next Typeinfo-next => eax
21091       eb/jump loop/disp8
21092     }
21093 $dump-typeinfos:end:
21094     # . restore registers
21095     58/pop-to-eax
21096     # . epilogue
21097     89/<- %esp 5/r32/ebp
21098     5d/pop-to-ebp
21099     c3/return
21100 
21101 dump-typeinfo:  # in: (addr typeinfo)
21102     # . prologue
21103     55/push-ebp
21104     89/<- %ebp 4/r32/esp
21105     # . save registers
21106     50/push-eax
21107     51/push-ecx
21108     52/push-edx
21109     53/push-ebx
21110     56/push-esi
21111     57/push-edi
21112     # esi = in
21113     8b/-> *(ebp+8) 6/r32/esi
21114     # var table/ecx: (addr table (handle array byte) (handle typeinfo-entry)) = lookup(T->fields)
21115     (lookup *(esi+4) *(esi+8))  # Typeinfo-fields Typeinfo-fields => eax
21116     89/<- %ecx 0/r32/eax
21117     (write-buffered Stderr "id:")
21118     (write-int32-hex-buffered Stderr *esi)
21119     (write-buffered Stderr "\n")
21120     (write-buffered Stderr "fields @ ")
21121     (write-int32-hex-buffered Stderr %ecx)
21122     (write-buffered Stderr Newline)
21123     (flush Stderr)
21124     (write-buffered Stderr "  write: ")
21125     (write-int32-hex-buffered Stderr *ecx)
21126     (write-buffered Stderr Newline)
21127     (flush Stderr)
21128     (write-buffered Stderr "  read: ")
21129     (write-int32-hex-buffered Stderr *(ecx+4))
21130     (write-buffered Stderr Newline)
21131     (flush Stderr)
21132     (write-buffered Stderr "  size: ")
21133     (write-int32-hex-buffered Stderr *(ecx+8))
21134     (write-buffered Stderr Newline)
21135     (flush Stderr)
21136     # var table-size/edx: int = table->write
21137     8b/-> *ecx 2/r32/edx  # stream-write
21138     # var curr/ecx: (addr table_row) = table->data
21139     8d/copy-address *(ecx+0xc) 1/r32/ecx
21140     # var max/edx: (addr table_row) = table->data + table->write
21141     8d/copy-address *(ecx+edx) 2/r32/edx
21142     {
21143 $dump-typeinfo:loop:
21144       # if (curr >= max) break
21145       39/compare %ecx 2/r32/edx
21146       0f 83/jump-if-addr>= break/disp32
21147       (write-buffered Stderr "  row:\n")
21148       (write-buffered Stderr "    key: ")
21149       (write-int32-hex-buffered Stderr *ecx)
21150       (write-buffered Stderr ",")
21151       (write-int32-hex-buffered Stderr *(ecx+4))
21152       (write-buffered Stderr " = '")
21153       (lookup *ecx *(ecx+4))
21154       (write-buffered Stderr %eax)
21155       (write-buffered Stderr "' @ ")
21156       (write-int32-hex-buffered Stderr %eax)
21157       (write-buffered Stderr Newline)
21158       (flush Stderr)
21159       (write-buffered Stderr "    value: ")
21160       (write-int32-hex-buffered Stderr *(ecx+8))
21161       (write-buffered Stderr ",")
21162       (write-int32-hex-buffered Stderr *(ecx+0xc))
21163       (write-buffered Stderr " = typeinfo-entry@")
21164       (lookup *(ecx+8) *(ecx+0xc))
21165       (write-int32-hex-buffered Stderr %eax)
21166       (write-buffered Stderr Newline)
21167       (flush Stderr)
21168       (write-buffered Stderr "        input var@")
21169       (dump-var 5 %eax)
21170       (lookup *(ecx+8) *(ecx+0xc))
21171       (write-buffered Stderr "        index: ")
21172       (write-int32-hex-buffered Stderr *(eax+8))
21173       (write-buffered Stderr Newline)
21174       (flush Stderr)
21175       (write-buffered Stderr "        output var@")
21176       8d/copy-address *(eax+0xc) 0/r32/eax  # Typeinfo-entry-output-var
21177       (dump-var 5 %eax)
21178       (flush Stderr)
21179       # curr += row-size
21180       81 0/subop/add %ecx 0x10/imm32  # Typeinfo-fields-row-size
21181       #
21182       e9/jump loop/disp32
21183     }
21184 $dump-typeinfo:end:
21185     # . restore registers
21186     5f/pop-to-edi
21187     5e/pop-to-esi
21188     5b/pop-to-ebx
21189     5a/pop-to-edx
21190     59/pop-to-ecx
21191     58/pop-to-eax
21192     # . epilogue
21193     89/<- %esp 5/r32/ebp
21194     5d/pop-to-ebp
21195     c3/return
21196 
21197 dump-var:  # indent: int, v: (addr handle var)
21198     # . prologue
21199     55/push-ebp
21200     89/<- %ebp 4/r32/esp
21201     # . save registers
21202     50/push-eax
21203     53/push-ebx
21204     # eax = v
21205     8b/-> *(ebp+0xc) 0/r32/eax
21206     #
21207     (write-int32-hex-buffered Stderr *eax)
21208     (write-buffered Stderr ",")
21209     (write-int32-hex-buffered Stderr *(eax+4))
21210     (write-buffered Stderr "->")
21211     (lookup *eax *(eax+4))
21212     (write-int32-hex-buffered Stderr %eax)
21213     (write-buffered Stderr Newline)
21214     (flush Stderr)
21215     {
21216       3d/compare-eax-and 0/imm32
21217       0f 84/jump-if-= break/disp32
21218       (emit-indent Stderr *(ebp+8))
21219       (write-buffered Stderr "name: ")
21220       89/<- %ebx 0/r32/eax
21221       (write-int32-hex-buffered Stderr *ebx)  # Var-name
21222       (write-buffered Stderr ",")
21223       (write-int32-hex-buffered Stderr *(ebx+4))  # Var-name
21224       (write-buffered Stderr "->")
21225       (lookup *ebx *(ebx+4))  # Var-name
21226       (write-int32-hex-buffered Stderr %eax)
21227       {
21228         3d/compare-eax-and 0/imm32
21229         74/jump-if-= break/disp8
21230         (write-buffered Stderr Space)
21231         (write-buffered Stderr %eax)
21232       }
21233       (write-buffered Stderr Newline)
21234       (flush Stderr)
21235       (emit-indent Stderr *(ebp+8))
21236       (write-buffered Stderr "block depth: ")
21237       (write-int32-hex-buffered Stderr *(ebx+0x10))  # Var-block-depth
21238       (write-buffered Stderr Newline)
21239       (flush Stderr)
21240       (emit-indent Stderr *(ebp+8))
21241       (write-buffered Stderr "stack offset: ")
21242       (write-int32-hex-buffered Stderr *(ebx+0x14))  # Var-offset
21243       (write-buffered Stderr Newline)
21244       (flush Stderr)
21245       (emit-indent Stderr *(ebp+8))
21246       (write-buffered Stderr "reg: ")
21247       (write-int32-hex-buffered Stderr *(ebx+0x18))  # Var-register
21248       (write-buffered Stderr ",")
21249       (write-int32-hex-buffered Stderr *(ebx+0x1c))  # Var-register
21250       (write-buffered Stderr "->")
21251       (flush Stderr)
21252       (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register
21253       (write-int32-hex-buffered Stderr %eax)
21254       {
21255         3d/compare-eax-and 0/imm32
21256         74/jump-if-= break/disp8
21257         (write-buffered Stderr Space)
21258         (write-buffered Stderr %eax)
21259       }
21260       (write-buffered Stderr Newline)
21261       (flush Stderr)
21262     }
21263 $dump-var:end:
21264     # . restore registers
21265     5b/pop-to-ebx
21266     58/pop-to-eax
21267     # . epilogue
21268     89/<- %esp 5/r32/ebp
21269     5d/pop-to-ebp
21270     c3/return
21271 
21272 #######################################################
21273 # Type-checking
21274 #######################################################
21275 
21276 check-mu-types:  # err: (addr buffered-file), ed: (addr exit-descriptor)
21277     # . prologue
21278     55/push-ebp
21279     89/<- %ebp 4/r32/esp
21280     # . save registers
21281     50/push-eax
21282     # var curr/eax: (addr function) = lookup(Program->functions)
21283     (lookup *_Program-functions *_Program-functions->payload)  # => eax
21284     {
21285 $check-mu-types:loop:
21286       # if (curr == null) break
21287       3d/compare-eax-and 0/imm32
21288       0f 84/jump-if-= break/disp32
21289 +--  8 lines: #?       # dump curr->name ------------------------------------------------------------------------------------------------------------------------------------------------
21297       (check-mu-function %eax *(ebp+8) *(ebp+0xc))
21298       # curr = lookup(curr->next)
21299       (lookup *(eax+0x20) *(eax+0x24))  # Function-next Function-next => eax
21300       e9/jump loop/disp32
21301     }
21302 $check-mu-types:end:
21303     # . restore registers
21304     58/pop-to-eax
21305     # . epilogue
21306     89/<- %esp 5/r32/ebp
21307     5d/pop-to-ebp
21308     c3/return
21309 
21310 check-mu-function:  # fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21311     # . prologue
21312     55/push-ebp
21313     89/<- %ebp 4/r32/esp
21314     # . save registers
21315     50/push-eax
21316     56/push-esi
21317     # esi = f
21318     8b/-> *(ebp+8) 6/r32/esi
21319     # outputs
21320     (lookup *(esi+0x10) *(esi+0x14))  # Function-outputs Function-outputs => eax
21321     (check-all-unique-registers %eax %esi *(ebp+0xc) *(ebp+0x10))
21322     # body
21323     (lookup *(esi+0x18) *(esi+0x1c))  # Function-body Function-body => eax
21324     (check-mu-block %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10))
21325     # if function has no outputs, we're done
21326     81 7/subop/compare *(esi+0x10) 0/imm32
21327     74/jump-if-= $check-mu-function:end/disp8
21328     # some final checks on body
21329     (check-final-stmt-is-return %eax %esi *(ebp+0xc) *(ebp+0x10))
21330     (check-no-breaks %eax %esi *(ebp+0xc) *(ebp+0x10))
21331 $check-mu-function:end:
21332     # . restore registers
21333     5e/pop-to-esi
21334     58/pop-to-eax
21335     # . epilogue
21336     89/<- %esp 5/r32/ebp
21337     5d/pop-to-ebp
21338     c3/return
21339 
21340 check-mu-block:  # block: (addr block), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21341     # . prologue
21342     55/push-ebp
21343     89/<- %ebp 4/r32/esp
21344     # . save registers
21345     50/push-eax
21346     # eax = block
21347     8b/-> *(ebp+8) 0/r32/eax
21348     # var stmts/eax: (addr list stmt) = lookup(block->statements)
21349     (lookup *(eax+4) *(eax+8))  # Block-stmts Block-stmts => eax
21350     #
21351     {
21352 $check-mu-block:check-empty:
21353       3d/compare-eax-and 0/imm32
21354       0f 84/jump-if-= break/disp32
21355       # emit block->statements
21356       (check-mu-stmt-list %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21357     }
21358 $check-mu-block:end:
21359     # . restore registers
21360     58/pop-to-eax
21361     # . epilogue
21362     89/<- %esp 5/r32/ebp
21363     5d/pop-to-ebp
21364     c3/return
21365 
21366 check-mu-stmt-list:  # stmts: (addr list stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21367     # . prologue
21368     55/push-ebp
21369     89/<- %ebp 4/r32/esp
21370     # . save registers
21371     50/push-eax
21372     56/push-esi
21373     # esi = stmts
21374     8b/-> *(ebp+8) 6/r32/esi
21375     {
21376 $check-mu-stmt-list:loop:
21377       81 7/subop/compare %esi 0/imm32
21378       0f 84/jump-if-= break/disp32
21379       # var curr-stmt/eax: (addr stmt) = lookup(stmts->value)
21380       (lookup *esi *(esi+4))  # List-value List-value => eax
21381       {
21382 $check-mu-stmt-list:check-for-block:
21383         81 7/subop/compare *eax 0/imm32/block  # Stmt-tag
21384         75/jump-if-!= break/disp8
21385 $check-mu-stmt-list:block:
21386         (check-mu-block %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21387         eb/jump $check-mu-stmt-list:continue/disp8
21388       }
21389       {
21390 $check-mu-stmt-list:check-for-stmt1:
21391         81 7/subop/compare *eax 1/imm32/stmt1  # Stmt-tag
21392         0f 85/jump-if-!= break/disp32
21393 $check-mu-stmt-list:stmt1:
21394         (check-mu-stmt %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21395         eb/jump $check-mu-stmt-list:continue/disp8
21396       }
21397       {
21398 $check-mu-stmt-list:check-for-reg-var-def:
21399         81 7/subop/compare *eax 3/imm32/reg-var-def  # Stmt-tag
21400         0f 85/jump-if-!= break/disp32
21401 $check-mu-stmt-list:reg-var-def:
21402         (check-mu-stmt %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21403         eb/jump $check-mu-stmt-list:continue/disp8
21404       }
21405 $check-mu-stmt-list:continue:
21406       # TODO: raise an error on unrecognized Stmt-tag
21407       (lookup *(esi+8) *(esi+0xc))  # List-next List-next => eax
21408       89/<- %esi 0/r32/eax
21409       e9/jump loop/disp32
21410     }
21411 $check-mu-stmt-list:end:
21412     # . restore registers
21413     5e/pop-to-esi
21414     58/pop-to-eax
21415     # . epilogue
21416     89/<- %esp 5/r32/ebp
21417     5d/pop-to-ebp
21418     c3/return
21419 
21420 check-mu-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21421     # . prologue
21422     55/push-ebp
21423     89/<- %ebp 4/r32/esp
21424     # . save registers
21425     50/push-eax
21426     # - if stmt's operation matches a primitive, check against it
21427     (has-primitive-name? *(ebp+8))  # => eax
21428     3d/compare-eax-and 0/imm32/false
21429     {
21430       74/jump-if-= break/disp8
21431       (check-mu-primitive *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21432       e9/jump $check-mu-stmt:end/disp32
21433     }
21434     # - otherwise find a function to check against
21435     # var f/eax: (addr function) = lookup(*Program->functions)
21436     (lookup *_Program-functions *_Program-functions->payload)  # => eax
21437     (find-matching-function %eax *(ebp+8))  # => eax
21438     3d/compare-eax-and 0/imm32
21439     {
21440       74/jump-if-= break/disp8
21441       (check-mu-call *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21442       eb/jump $check-mu-stmt:end/disp8
21443     }
21444     # var f/eax: (addr function) = lookup(*Program->signatures)
21445     (lookup *_Program-signatures *_Program-signatures->payload)  # => eax
21446     (find-matching-function %eax *(ebp+8))  # => eax
21447     3d/compare-eax-and 0/imm32
21448     {
21449       74/jump-if-= break/disp8
21450       (check-mu-call *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21451       eb/jump $check-mu-stmt:end/disp8
21452     }
21453     # - otherwise abort
21454     e9/jump $check-mu-stmt:unknown-call/disp32
21455 $check-mu-stmt:end:
21456     # . restore registers
21457     58/pop-to-eax
21458     # . epilogue
21459     89/<- %esp 5/r32/ebp
21460     5d/pop-to-ebp
21461     c3/return
21462 
21463 $check-mu-stmt:unknown-call:
21464     (write-buffered *(ebp+0x10) "unknown function '")
21465     8b/-> *(ebp+8) 0/r32/eax
21466     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
21467     (write-buffered *(ebp+0x10) %eax)
21468     (write-buffered *(ebp+0x10) "'\n")
21469     (flush *(ebp+0x10))
21470     (stop *(ebp+0x14) 1)
21471     # never gets here
21472 
21473 has-primitive-name?:  # stmt: (addr stmt) -> result/eax: boolean
21474     # . prologue
21475     55/push-ebp
21476     89/<- %ebp 4/r32/esp
21477     # . save registers
21478     51/push-ecx
21479     56/push-esi
21480     # var name/esi: (addr array byte) = lookup(stmt->operation)
21481     8b/-> *(ebp+8) 6/r32/esi
21482     (lookup *(esi+4) *(esi+8))  # Stmt1-operation Stmt1-operation => eax
21483     89/<- %esi 0/r32/eax
21484     # if (name == "return") return true
21485     (string-equal? %esi "return")  # => eax
21486     3d/compare-eax-and 0/imm32/false
21487     0f 85/jump-if-!= $has-primitive-name?:end/disp32
21488     # if (name == "get") return true
21489     (string-equal? %esi "get")  # => eax
21490     3d/compare-eax-and 0/imm32/false
21491     0f 85/jump-if-!= $has-primitive-name?:end/disp32
21492     # if (name == "index") return true
21493     (string-equal? %esi "index")  # => eax
21494     3d/compare-eax-and 0/imm32/false
21495     0f 85/jump-if-!= $has-primitive-name?:end/disp32
21496     # if (name == "length") return true
21497     (string-equal? %esi "length")  # => eax
21498     3d/compare-eax-and 0/imm32/false
21499     0f 85/jump-if-!= $has-primitive-name?:end/disp32
21500     # if (name == "compute-offset") return true
21501     (string-equal? %esi "compute-offset")  # => eax
21502     3d/compare-eax-and 0/imm32/false
21503     0f 85/jump-if-!= $has-primitive-name?:end/disp32
21504     # if (name == "copy-object") return true
21505     (string-equal? %esi "copy-object")  # => eax
21506     3d/compare-eax-and 0/imm32/false
21507     0f 85/jump-if-!= $has-primitive-name?:end/disp32
21508     # if (name == "clear-object") return true
21509     (string-equal? %esi "clear-object")  # => eax
21510     3d/compare-eax-and 0/imm32/false
21511     0f 85/jump-if-!= $has-primitive-name?:end/disp32
21512     # if (name == "allocate") return true
21513     (string-equal? %esi "allocate")  # => eax
21514     3d/compare-eax-and 0/imm32/false
21515     0f 85/jump-if-!= $has-primitive-name?:end/disp32
21516     # if (name == "populate") return true
21517     (string-equal? %esi "populate")  # => eax
21518     3d/compare-eax-and 0/imm32/false
21519     0f 85/jump-if-!= $has-primitive-name?:end/disp32
21520     # if (name == "populate-stream") return true
21521     (string-equal? %esi "populate-stream")  # => eax
21522     3d/compare-eax-and 0/imm32/false
21523     0f 85/jump-if-!= $has-primitive-name?:end/disp32
21524     # if (name == "read-from-stream") return true
21525     (string-equal? %esi "read-from-stream")  # => eax
21526     3d/compare-eax-and 0/imm32/false
21527     0f 85/jump-if-!= $has-primitive-name?:end/disp32
21528     # if (name == "write-to-stream") return true
21529     (string-equal? %esi "write-to-stream")  # => eax
21530     3d/compare-eax-and 0/imm32/false
21531     0f 85/jump-if-!= $has-primitive-name?:end/disp32
21532     # var curr/ecx: (addr primitive) = Primitives
21533     b9/copy-to-ecx Primitives/imm32
21534     {
21535 $has-primitive-name?:loop:
21536       # if (curr == null) break
21537       81 7/subop/compare %ecx 0/imm32
21538       74/jump-if-= break/disp8
21539       # if (primitive->name == name) return true
21540       (lookup *ecx *(ecx+4))  # Primitive-name Primitive-name => eax
21541 #?       (write-buffered Stderr %eax)
21542 #?       (write-buffered Stderr Newline)
21543 #?       (flush Stderr)
21544       (string-equal? %esi %eax)  # => eax
21545       3d/compare-eax-and 0/imm32/false
21546       75/jump-if-!= $has-primitive-name?:end/disp8
21547 $has-primitive-name?:next-primitive:
21548       # curr = curr->next
21549       (lookup *(ecx+0x3c) *(ecx+0x40))  # Primitive-next Primitive-next => eax
21550       89/<- %ecx 0/r32/eax
21551       #
21552       e9/jump loop/disp32
21553     }
21554     # return null
21555     b8/copy-to-eax 0/imm32
21556 $has-primitive-name?:end:
21557     # . restore registers
21558     5e/pop-to-esi
21559     59/pop-to-ecx
21560     # . epilogue
21561     89/<- %esp 5/r32/ebp
21562     5d/pop-to-ebp
21563     c3/return
21564 
21565 check-mu-primitive:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21566     # . prologue
21567     55/push-ebp
21568     89/<- %ebp 4/r32/esp
21569     # . save registers
21570     50/push-eax
21571     51/push-ecx
21572     # var op/ecx: (addr array byte) = lookup(stmt->operation)
21573     8b/-> *(ebp+8) 0/r32/eax
21574     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
21575     89/<- %ecx 0/r32/eax
21576     # if (op == "copy") check-mu-copy-stmt
21577     {
21578       (string-equal? %ecx "copy")  # => eax
21579       3d/compare-eax-and 0/imm32/false
21580       74/jump-if-= break/disp8
21581       (check-mu-copy-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21582       e9/jump $check-mu-primitive:end/disp32
21583     }
21584     # if (op == "copy-to") check-mu-copy-to-stmt
21585     {
21586       (string-equal? %ecx "copy-to")  # => eax
21587       3d/compare-eax-and 0/imm32/false
21588       74/jump-if-= break/disp8
21589       (check-mu-copy-to-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21590       e9/jump $check-mu-primitive:end/disp32
21591     }
21592     # if (op == "copy-byte") check-mu-copy-byte-stmt
21593     {
21594       (string-equal? %ecx "copy-byte")  # => eax
21595       3d/compare-eax-and 0/imm32/false
21596       74/jump-if-= break/disp8
21597       (check-mu-copy-byte-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21598       e9/jump $check-mu-primitive:end/disp32
21599     }
21600     # if (op == "copy-byte-to") check-mu-copy-byte-to-stmt
21601     {
21602       (string-equal? %ecx "copy-byte-to")  # => eax
21603       3d/compare-eax-and 0/imm32/false
21604       74/jump-if-= break/disp8
21605       (check-mu-copy-byte-to-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21606       e9/jump $check-mu-primitive:end/disp32
21607     }
21608     # if (op == "compare") check-mu-compare-stmt
21609     {
21610       (string-equal? %ecx "compare")  # => eax
21611       3d/compare-eax-and 0/imm32/false
21612       74/jump-if-= break/disp8
21613       (check-mu-compare-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21614       e9/jump $check-mu-primitive:end/disp32
21615     }
21616     # if (op == "address") check-mu-address-stmt
21617     {
21618       (string-equal? %ecx "address")  # => eax
21619       3d/compare-eax-and 0/imm32/false
21620       74/jump-if-= break/disp8
21621       (check-mu-address-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21622       e9/jump $check-mu-primitive:end/disp32
21623     }
21624     # if (op == "return") check-mu-return-stmt
21625     {
21626       (string-equal? %ecx "return")  # => eax
21627       3d/compare-eax-and 0/imm32/false
21628       74/jump-if-= break/disp8
21629       (check-mu-return-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21630       e9/jump $check-mu-primitive:end/disp32
21631     }
21632     # if (op == "get") check-mu-get-stmt
21633     {
21634       (string-equal? %ecx "get")  # => eax
21635       3d/compare-eax-and 0/imm32/false
21636       74/jump-if-= break/disp8
21637       (check-mu-get-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21638       e9/jump $check-mu-primitive:end/disp32
21639     }
21640     # if (op == "index") check-mu-index-stmt
21641     {
21642       (string-equal? %ecx "index")  # => eax
21643       3d/compare-eax-and 0/imm32/false
21644       74/jump-if-= break/disp8
21645       (check-mu-index-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21646       e9/jump $check-mu-primitive:end/disp32
21647     }
21648     # if (op == "length") check-mu-length-stmt
21649     {
21650       (string-equal? %ecx "length")  # => eax
21651       3d/compare-eax-and 0/imm32/false
21652       74/jump-if-= break/disp8
21653       (check-mu-length-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21654       e9/jump $check-mu-primitive:end/disp32
21655     }
21656     # if (op == "compute-offset") check-mu-compute-offset-stmt
21657     {
21658       (string-equal? %ecx "compute-offset")  # => eax
21659       3d/compare-eax-and 0/imm32/false
21660       74/jump-if-= break/disp8
21661       (check-mu-compute-offset-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21662       e9/jump $check-mu-primitive:end/disp32
21663     }
21664     # if (op == "copy-object") check-mu-copy-object-stmt
21665     {
21666       (string-equal? %ecx "copy-object")  # => eax
21667       3d/compare-eax-and 0/imm32/false
21668       74/jump-if-= break/disp8
21669       (check-mu-copy-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21670       e9/jump $check-mu-primitive:end/disp32
21671     }
21672     # if (op == "clear-object") check-mu-clear-object-stmt
21673     {
21674       (string-equal? %ecx "clear-object")  # => eax
21675       3d/compare-eax-and 0/imm32/false
21676       74/jump-if-= break/disp8
21677       (check-mu-clear-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21678       e9/jump $check-mu-primitive:end/disp32
21679     }
21680     # if (op == "allocate") check-mu-allocate-stmt
21681     {
21682       (string-equal? %ecx "allocate")  # => eax
21683       3d/compare-eax-and 0/imm32/false
21684       74/jump-if-= break/disp8
21685       (check-mu-allocate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21686       e9/jump $check-mu-primitive:end/disp32
21687     }
21688     # if (op == "populate") check-mu-populate-stmt
21689     {
21690       (string-equal? %ecx "populate")  # => eax
21691       3d/compare-eax-and 0/imm32/false
21692       74/jump-if-= break/disp8
21693       (check-mu-populate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21694       e9/jump $check-mu-primitive:end/disp32
21695     }
21696     # if (op == "populate-stream") check-mu-populate-stream-stmt
21697     {
21698       (string-equal? %ecx "populate-stream")  # => eax
21699       3d/compare-eax-and 0/imm32/false
21700       74/jump-if-= break/disp8
21701       (check-mu-populate-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21702       e9/jump $check-mu-primitive:end/disp32
21703     }
21704     # if (op == "read-from-stream") check-mu-read-from-stream-stmt
21705     {
21706       (string-equal? %ecx "read-from-stream")  # => eax
21707       3d/compare-eax-and 0/imm32/false
21708       74/jump-if-= break/disp8
21709       (check-mu-read-from-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21710       e9/jump $check-mu-primitive:end/disp32
21711     }
21712     # if (op == "write-to-stream") check-mu-write-to-stream-stmt
21713     {
21714       (string-equal? %ecx "write-to-stream")  # => eax
21715       3d/compare-eax-and 0/imm32/false
21716       74/jump-if-= break/disp8
21717       (check-mu-write-to-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21718       e9/jump $check-mu-primitive:end/disp32
21719     }
21720     # if (op == "convert") check-mu-convert-stmt
21721     {
21722       (string-equal? %ecx "convert")  # => eax
21723       3d/compare-eax-and 0/imm32/false
21724       74/jump-if-= break/disp8
21725       (check-mu-convert-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21726       e9/jump $check-mu-primitive:end/disp32
21727     }
21728     # otherwise check-numberlike-stmt
21729     (check-mu-numberlike-primitive *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21730 $check-mu-primitive:end:
21731     # . restore registers
21732     59/pop-to-ecx
21733     58/pop-to-eax
21734     # . epilogue
21735     89/<- %esp 5/r32/ebp
21736     5d/pop-to-ebp
21737     c3/return
21738 
21739 # by default, Mu primitives should only operate on 'number-like' types
21740 check-mu-numberlike-primitive:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21741     # . prologue
21742     55/push-ebp
21743     89/<- %ebp 4/r32/esp
21744     # . save registers
21745     50/push-eax
21746     51/push-ecx
21747     56/push-esi
21748     # esi = stmt
21749     8b/-> *(ebp+8) 6/r32/esi
21750     # var gas/ecx: int = 2
21751     b9/copy-to-ecx 2/imm32
21752     # - check at most 1 output
21753     # var output/eax: (addr stmt-var) = stmt->outputs
21754     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
21755     {
21756       3d/compare-eax-and 0/imm32
21757       74/jump-if-= break/disp8
21758 $check-mu-numberlike-primitive:output:
21759       (check-mu-numberlike-output %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21760       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
21761       3d/compare-eax-and 0/imm32
21762       0f 85/jump-if-!= $check-mu-numberlike-primitive:error-too-many-outputs/disp32
21763       # check output is in a register
21764       # --gas
21765       49/decrement-ecx
21766     }
21767     # - check first inout
21768     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
21769     {
21770       3d/compare-eax-and 0/imm32
21771       0f 84/jump-if-= $check-mu-numberlike-primitive:end/disp32
21772 $check-mu-numberlike-primitive:first-inout:
21773       (check-mu-numberlike-arg %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21774       # --gas
21775       49/decrement-ecx
21776     }
21777     # - check second inout
21778     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
21779     {
21780       3d/compare-eax-and 0/imm32
21781       74/jump-if-= $check-mu-numberlike-primitive:end/disp8
21782 $check-mu-numberlike-primitive:second-inout:
21783       # is a second inout allowed?
21784       81 7/subop/compare %ecx 0/imm32
21785       0f 84/jump-if-= $check-mu-numberlike-primitive:error-too-many-inouts/disp32
21786 $check-mu-numberlike-primitive:second-inout-permitted:
21787       (check-mu-numberlike-arg %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21788     }
21789 $check-mu-numberlike-primitive:third-inout:
21790     # if there's a third arg, raise an error
21791     81 7/subop/compare *(eax+8) 0/imm32  # Stmt-var-next
21792     0f 85/jump-if-!= $check-mu-numberlike-primitive:error-too-many-inouts/disp32
21793 $check-mu-numberlike-primitive:end:
21794     # . restore registers
21795     5e/pop-to-esi
21796     59/pop-to-ecx
21797     58/pop-to-eax
21798     # . epilogue
21799     89/<- %esp 5/r32/ebp
21800     5d/pop-to-ebp
21801     c3/return
21802 
21803 $check-mu-numberlike-primitive:error-too-many-inouts:
21804     (write-buffered *(ebp+0x10) "fn ")
21805     8b/-> *(ebp+0xc) 0/r32/eax
21806     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21807     (write-buffered *(ebp+0x10) %eax)
21808     (write-buffered *(ebp+0x10) ": stmt ")
21809     (lookup *(esi+4) *(esi+8))  # Stmt1-operation Stmt1-operation => eax
21810     (write-buffered *(ebp+0x10) %eax)
21811     (write-buffered *(ebp+0x10) ": too many inouts; most primitives support at most two arguments, across inouts and outputs\n")
21812     (flush *(ebp+0x10))
21813     (stop *(ebp+0x14) 1)
21814     # never gets here
21815 
21816 $check-mu-numberlike-primitive:error-too-many-outputs:
21817     (write-buffered *(ebp+0x10) "fn ")
21818     8b/-> *(ebp+0xc) 0/r32/eax
21819     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21820     (write-buffered *(ebp+0x10) %eax)
21821     (write-buffered *(ebp+0x10) ": stmt ")
21822     (lookup *(esi+4) *(esi+8))  # Stmt1-operation Stmt1-operation => eax
21823     (write-buffered *(ebp+0x10) %eax)
21824     (write-buffered *(ebp+0x10) ": too many outputs; most primitives support at most one output\n")
21825     (flush *(ebp+0x10))
21826     (stop *(ebp+0x14) 1)
21827     # never gets here
21828 
21829 check-mu-numberlike-arg:  # v: (addr stmt-var), stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21830     # . prologue
21831     55/push-ebp
21832     89/<- %ebp 4/r32/esp
21833     # . save registers
21834     50/push-eax
21835     56/push-esi
21836     # var t/esi: (addr type-tree) = lookup(v->value->type)
21837     8b/-> *(ebp+8) 0/r32/eax
21838     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
21839     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
21840     89/<- %esi 0/r32/eax
21841 $check-mu-numberlike-arg:check-literal:
21842     # if t is an int, return
21843     (simple-mu-type? %esi 0)  # literal => eax
21844     3d/compare-eax-and 0/imm32/false
21845     0f 85/jump-if-!= $check-mu-numberlike-arg:end/disp32
21846 $check-mu-numberlike-arg:check-addr:
21847     # if t is an addr and v is dereferenced, return whether t->payload is an addr
21848     {
21849       (mu-addr-type? %esi)  # => eax
21850       3d/compare-eax-and 0/imm32/false
21851       74/jump-if-= break/disp8
21852       8b/-> *(ebp+8) 0/r32/eax
21853       8b/-> *(eax+0x10) 0/r32/eax  # Stmt-var-is-deref
21854       3d/compare-eax-and 0/imm32/false
21855       {
21856         74/jump-if-= break/disp8
21857         (lookup *(esi+0xc) *(esi+0x10))  # Type-tree-right Type-tree-right => eax
21858         # if t->right is null, t = t->left
21859         81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
21860         {
21861           75/jump-if-!= break/disp8
21862           (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
21863         }
21864         (mu-addr-type? %eax)  # => eax
21865         3d/compare-eax-and 0/imm32/false
21866         74/jump-if-= $check-mu-numberlike-arg:end/disp8
21867       }
21868     }
21869 $check-mu-numberlike-arg:output-checks:
21870     (check-mu-numberlike-output *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18))
21871 $check-mu-numberlike-arg:end:
21872     # . restore registers
21873     5e/pop-to-esi
21874     58/pop-to-eax
21875     # . epilogue
21876     89/<- %esp 5/r32/ebp
21877     5d/pop-to-ebp
21878     c3/return
21879 
21880 check-mu-numberlike-output:  # v: (addr stmt-var), stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21881     # . prologue
21882     55/push-ebp
21883     89/<- %ebp 4/r32/esp
21884     # . save registers
21885     50/push-eax
21886     #
21887     (mu-numberlike-output-var? *(ebp+8))  # => eax
21888     3d/compare-eax-and 0/imm32/false
21889     0f 84/jump-if-= $check-mu-numberlike-output:fail/disp32
21890 $check-mu-numberlike-output:end:
21891     # . restore registers
21892     58/pop-to-eax
21893     # . epilogue
21894     89/<- %esp 5/r32/ebp
21895     5d/pop-to-ebp
21896     c3/return
21897 
21898 $check-mu-numberlike-output:fail:
21899     # otherwise raise an error
21900     (write-buffered *(ebp+0x14) "fn ")
21901     8b/-> *(ebp+0x10) 0/r32/eax
21902     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21903     (write-buffered *(ebp+0x14) %eax)
21904     (write-buffered *(ebp+0x14) ": stmt ")
21905     8b/-> *(ebp+0xc) 0/r32/eax
21906     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
21907     (write-buffered *(ebp+0x14) %eax)
21908     (write-buffered *(ebp+0x14) ": '")
21909     8b/-> *(ebp+8) 0/r32/eax
21910     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
21911     (lookup *eax *(eax+4))  # Var-name Var-name => eax
21912     (write-buffered *(ebp+0x14) %eax)
21913     (write-buffered *(ebp+0x14) "' must be a non-addr non-offset scalar\n")
21914     (flush *(ebp+0x14))
21915     (stop *(ebp+0x18) 1)
21916     # never gets here
21917 
21918 mu-numberlike-output-var?:  # v: (addr stmt-var) -> result/eax: boolean
21919     # . prologue
21920     55/push-ebp
21921     89/<- %ebp 4/r32/esp
21922     #
21923     8b/-> *(ebp+8) 0/r32/eax
21924     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
21925     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
21926     (mu-numberlike-output? %eax)  # => eax
21927 $mu-numberlike-output-var?:end:
21928     # . epilogue
21929     89/<- %esp 5/r32/ebp
21930     5d/pop-to-ebp
21931     c3/return
21932 
21933 mu-numberlike-output?:  # v: (addr type-tree) -> result/eax: boolean
21934     # . prologue
21935     55/push-ebp
21936     89/<- %ebp 4/r32/esp
21937     # . save registers
21938     56/push-esi
21939     # var t/esi: (addr type-tree) = lookup(v->value->type)
21940     8b/-> *(ebp+8) 6/r32/esi
21941 $mu-numberlike-output?:check-int:
21942     # if t is an int, return
21943     (simple-mu-type? %esi 1)  # int => eax
21944     3d/compare-eax-and 0/imm32/false
21945     0f 85/jump-if-!= $mu-numberlike-output?:return-true/disp32
21946 $mu-numberlike-output?:check-float:
21947     # if t is a float, return
21948     (simple-mu-type? %esi 0xf)  # float => eax
21949     3d/compare-eax-and 0/imm32/false
21950     75/jump-if-!= $mu-numberlike-output?:return-true/disp8
21951 $mu-numberlike-output?:check-boolean:
21952     # if t is a boolean, return
21953     (simple-mu-type? %esi 5)  # boolean => eax
21954     3d/compare-eax-and 0/imm32/false
21955     75/jump-if-!= $mu-numberlike-output?:return-true/disp8
21956 $mu-numberlike-output?:check-byte:
21957     # if t is a byte, return
21958     (simple-mu-type? %esi 8)  # byte => eax
21959     3d/compare-eax-and 0/imm32/false
21960     75/jump-if-!= $mu-numberlike-output?:return-true/disp8
21961 $mu-numberlike-output?:check-code-point:
21962     # if t is a code-point, return
21963     (simple-mu-type? %esi 0xd)  # code-point => eax
21964     3d/compare-eax-and 0/imm32/false
21965     75/jump-if-!= $mu-numberlike-output?:return-true/disp8
21966 $mu-numberlike-output?:check-grapheme:
21967     # if t is a grapheme, return
21968     (simple-mu-type? %esi 0xe)  # grapheme => eax
21969     3d/compare-eax-and 0/imm32/false
21970     75/jump-if-!= $mu-numberlike-output?:return-true/disp8
21971 $mu-numberlike-output?:return-false:
21972     b8/copy-to-eax 0/imm32/false
21973     eb/jump $mu-numberlike-output?:end/disp8
21974 $mu-numberlike-output?:return-true:
21975     b8/copy-to-eax 1/imm32/true
21976 $mu-numberlike-output?:end:
21977     # . restore registers
21978     5e/pop-to-esi
21979     # . epilogue
21980     89/<- %esp 5/r32/ebp
21981     5d/pop-to-ebp
21982     c3/return
21983 
21984 check-mu-copy-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21985     # . prologue
21986     55/push-ebp
21987     89/<- %ebp 4/r32/esp
21988     # . save registers
21989     50/push-eax
21990     51/push-ecx
21991     52/push-edx
21992     56/push-esi
21993     57/push-edi
21994     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
21995     81 5/subop/subtract %esp 0x60/imm32
21996     68/push 0x60/imm32/size
21997     68/push 0/imm32/read
21998     68/push 0/imm32/write
21999     89/<- %edx 4/r32/esp
22000 $check-mu-copy-stmt:get-output:
22001     # esi = stmt
22002     8b/-> *(ebp+8) 6/r32/esi
22003     # var output/edi: (addr stmt-var) = stmt->outputs
22004     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
22005     89/<- %edi 0/r32/eax
22006     # zero outputs
22007     3d/compare-eax-and 0/imm32
22008     0f 84/jump-if-= $check-mu-copy-stmt:error-no-output/disp32
22009     # > 1 output
22010     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
22011     3d/compare-eax-and 0/imm32
22012     0f 85/jump-if-!= $check-mu-copy-stmt:error-too-many-outputs/disp32
22013 $check-mu-copy-stmt:get-inout:
22014     # var inout/esi: (addr stmt-var) = stmt->inouts
22015     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22016     89/<- %esi 0/r32/eax
22017     # zero inouts
22018     3d/compare-eax-and 0/imm32
22019     0f 84/jump-if-= $check-mu-copy-stmt:error-no-inout/disp32
22020     # > 1 inout
22021     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
22022     3d/compare-eax-and 0/imm32
22023     0f 85/jump-if-!= $check-mu-copy-stmt:error-too-many-inouts/disp32
22024 $check-mu-copy-stmt:types:
22025     # if inout is not a scalar, abort
22026     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22027     (size-of %eax)  # => eax
22028     3d/compare-eax-and 4/imm32
22029     0f 8f/jump-if-> $check-mu-copy-stmt:error-inout-too-large/disp32
22030     # var inout-type/ecx: (addr type-tree) = inout->value->type
22031     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22032     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22033     89/<- %ecx 0/r32/eax
22034     # if (inout->is-deref?) inout-type = inout-type->payload
22035     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
22036     3d/compare-eax-and 0/imm32/false
22037     {
22038       74/jump-if-= break/disp8
22039       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
22040       # if inout-type->right is null, t = inout-type->left
22041       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
22042       {
22043         75/jump-if-!= break/disp8
22044         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
22045       }
22046       89/<- %ecx 0/r32/eax
22047     }
22048     # if output not in register, abort
22049     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22050     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
22051     3d/compare-eax-and 0/imm32
22052     0f 84/jump-if-= $check-mu-copy-stmt:error-output-not-in-register/disp32
22053     # var output-type/eax: (addr type-tree) = output->value->type
22054     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22055     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22056     # if (inout-type == output-type) return
22057     (type-match? %eax %ecx %edx)  # => eax
22058     3d/compare-eax-and 0/imm32
22059     0f 85/jump-if-!= $check-mu-copy-stmt:end/disp32
22060     # if output is an addr and inout is 0, return
22061     {
22062       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22063       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22064       (mu-addr-type? %eax)  # => eax
22065       3d/compare-eax-and 0/imm32/false
22066       74/jump-if-= break/disp8
22067       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22068       (lookup *eax *(eax+4))  # Var-name Var-name => eax
22069       (string-equal? %eax "0")  # => eax
22070       3d/compare-eax-and 0/imm32/false
22071       74/jump-if-= break/disp8
22072       e9/jump $check-mu-copy-stmt:end/disp32
22073     }
22074     # if output is an offset and inout is 0, return
22075     {
22076       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22077       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22078       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
22079       75/jump-if-!= break/disp8
22080       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
22081       (simple-mu-type? %eax 7)  # offset => eax
22082       3d/compare-eax-and 0/imm32/false
22083       74/jump-if-= break/disp8
22084       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22085       (lookup *eax *(eax+4))  # Var-name Var-name => eax
22086       (string-equal? %eax "0")  # => eax
22087       3d/compare-eax-and 0/imm32/false
22088       74/jump-if-= break/disp8
22089       e9/jump $check-mu-copy-stmt:end/disp32
22090     }
22091     # if output is a byte, abort if inout is not a literal. Otherwise return.
22092     {
22093       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22094       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22095       (simple-mu-type? %eax 8)  # byte => eax
22096       3d/compare-eax-and 0/imm32/false
22097       74/jump-if-= break/disp8
22098       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22099       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22100       (simple-mu-type? %eax 0)  # literal => eax
22101       3d/compare-eax-and 0/imm32/false
22102       0f 84/jump-if-= $check-mu-copy-stmt:error-non-literal-to-byte/disp32
22103       eb/jump $check-mu-copy-stmt:end/disp8
22104     }
22105     # if output is not number-like, abort
22106     (check-mu-numberlike-output %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
22107 $check-mu-copy-stmt:end:
22108     # . reclaim locals
22109     81 0/subop/add %esp 0x6c/imm32
22110     # . restore registers
22111     5f/pop-to-edi
22112     5e/pop-to-esi
22113     5a/pop-to-edx
22114     59/pop-to-ecx
22115     58/pop-to-eax
22116     # . epilogue
22117     89/<- %esp 5/r32/ebp
22118     5d/pop-to-ebp
22119     c3/return
22120 
22121 $check-mu-copy-stmt:error-no-inout:
22122     (write-buffered *(ebp+0x10) "fn ")
22123     8b/-> *(ebp+0xc) 0/r32/eax
22124     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22125     (write-buffered *(ebp+0x10) %eax)
22126     (write-buffered *(ebp+0x10) ": stmt 'copy' expects an inout\n")
22127     (flush *(ebp+0x10))
22128     (stop *(ebp+0x14) 1)
22129     # never gets here
22130 
22131 $check-mu-copy-stmt:error-too-many-inouts:
22132     (write-buffered *(ebp+0x10) "fn ")
22133     8b/-> *(ebp+0xc) 0/r32/eax
22134     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22135     (write-buffered *(ebp+0x10) %eax)
22136     (write-buffered *(ebp+0x10) ": stmt 'copy' must have just one inout\n")
22137     (flush *(ebp+0x10))
22138     (stop *(ebp+0x14) 1)
22139     # never gets here
22140 
22141 $check-mu-copy-stmt:error-no-output:
22142     (write-buffered *(ebp+0x10) "fn ")
22143     8b/-> *(ebp+0xc) 0/r32/eax
22144     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22145     (write-buffered *(ebp+0x10) %eax)
22146     (write-buffered *(ebp+0x10) ": stmt 'copy' expects an output\n")
22147     (flush *(ebp+0x10))
22148     (stop *(ebp+0x14) 1)
22149     # never gets here
22150 
22151 $check-mu-copy-stmt:error-output-not-in-register:
22152     (write-buffered *(ebp+0x10) "fn ")
22153     8b/-> *(ebp+0xc) 0/r32/eax
22154     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22155     (write-buffered *(ebp+0x10) %eax)
22156     (write-buffered *(ebp+0x10) ": stmt copy: output '")
22157     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22158     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22159     (write-buffered *(ebp+0x10) %eax)
22160     (write-buffered *(ebp+0x10) "' not in a register\n")
22161     (flush *(ebp+0x10))
22162     (stop *(ebp+0x14) 1)
22163     # never gets here
22164 
22165 $check-mu-copy-stmt:error-too-many-outputs:
22166     (write-buffered *(ebp+0x10) "fn ")
22167     8b/-> *(ebp+0xc) 0/r32/eax
22168     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22169     (write-buffered *(ebp+0x10) %eax)
22170     (write-buffered *(ebp+0x10) ": stmt 'copy' must have just one output\n")
22171     (flush *(ebp+0x10))
22172     (stop *(ebp+0x14) 1)
22173     # never gets here
22174 
22175 $check-mu-copy-stmt:error-inout-too-large:
22176     (write-buffered *(ebp+0x10) "fn ")
22177     8b/-> *(ebp+0xc) 0/r32/eax
22178     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22179     (write-buffered *(ebp+0x10) %eax)
22180     (write-buffered *(ebp+0x10) ": stmt copy: '")
22181     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22182     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22183     (write-buffered *(ebp+0x10) %eax)
22184     (write-buffered *(ebp+0x10) "' is too large to fit in a register\n")
22185     (flush *(ebp+0x10))
22186     (stop *(ebp+0x14) 1)
22187     # never gets here
22188 
22189 $check-mu-copy-stmt:error-non-literal-to-byte:
22190     (write-buffered *(ebp+0x10) "fn ")
22191     8b/-> *(ebp+0xc) 0/r32/eax
22192     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22193     (write-buffered *(ebp+0x10) %eax)
22194     (write-buffered *(ebp+0x10) ": stmt copy: cannot copy non-literal to '")
22195     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22196     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22197     (write-buffered *(ebp+0x10) %eax)
22198     (write-buffered *(ebp+0x10) "' of type byte; use copy-byte\n")
22199     (flush *(ebp+0x10))
22200     (stop *(ebp+0x14) 1)
22201     # never gets here
22202 
22203 check-mu-copy-to-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
22204     # . prologue
22205     55/push-ebp
22206     89/<- %ebp 4/r32/esp
22207     # . save registers
22208     50/push-eax
22209     51/push-ecx
22210     52/push-edx
22211     53/push-ebx
22212     56/push-esi
22213     57/push-edi
22214     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
22215     81 5/subop/subtract %esp 0x60/imm32
22216     68/push 0x60/imm32/size
22217     68/push 0/imm32/read
22218     68/push 0/imm32/write
22219     89/<- %edx 4/r32/esp
22220     # esi = stmt
22221     8b/-> *(ebp+8) 6/r32/esi
22222 $check-mu-copy-to-stmt:check-for-output:
22223     # if stmt->outputs abort
22224     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
22225     3d/compare-eax-and 0/imm32
22226     0f 85/jump-if-!= $check-mu-copy-to-stmt:error-too-many-outputs/disp32
22227 $check-mu-copy-to-stmt:get-dest:
22228     # var dest/edi: (addr stmt-var) = stmt->inouts
22229     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22230     89/<- %edi 0/r32/eax
22231     # zero inouts
22232     3d/compare-eax-and 0/imm32
22233     0f 84/jump-if-= $check-mu-copy-to-stmt:error-incorrect-inouts/disp32
22234 $check-mu-copy-to-stmt:get-src:
22235     # var src/esi: (addr stmt-var) = dest->next
22236     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
22237     89/<- %esi 0/r32/eax
22238     # 1 inout
22239     3d/compare-eax-and 0/imm32
22240     0f 84/jump-if-= $check-mu-copy-to-stmt:error-incorrect-inouts/disp32
22241     # > 2 inouts
22242     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
22243     3d/compare-eax-and 0/imm32
22244     0f 85/jump-if-!= $check-mu-copy-to-stmt:error-incorrect-inouts/disp32
22245 $check-mu-copy-to-stmt:types:
22246     # if src is not a scalar, abort
22247     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22248     (size-of %eax)  # => eax
22249     3d/compare-eax-and 4/imm32
22250     0f 8f/jump-if-> $check-mu-copy-to-stmt:error-src-too-large/disp32
22251     # var src-type/ecx: (addr type-tree) = src->value->type
22252     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22253     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22254     89/<- %ecx 0/r32/eax
22255     # if src not in register or literal, abort
22256     # (we can't use stack-offset because it hasn't been computed yet)
22257     {
22258       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22259       (lookup *(eax+0x8) *(eax+0xc))  # Var-type Var-type => eax
22260       (simple-mu-type? %eax 0)  # => eax
22261       3d/compare-eax-and 0/imm32
22262       75/jump-if-!= break/disp8
22263       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22264       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
22265       3d/compare-eax-and 0/imm32
22266       75/jump-if-!= break/disp8
22267       e9/jump $check-mu-copy-to-stmt:error-src-not-literal-or-in-register/disp32
22268     }
22269     # var dest-type/ebx: (addr type-tree) = dest->value->type
22270     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22271     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22272     89/<- %ebx 0/r32/eax
22273     # if (dest->is-deref?) dest-type = dest-type->payload
22274 $check-mu-copy-to-stmt:check-dest-deref:
22275     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
22276     3d/compare-eax-and 0/imm32/false
22277     {
22278       74/jump-if-= break/disp8
22279       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
22280 $check-mu-copy-to-stmt:dest-is-deref:
22281       # if dest-type->right is null, dest-type = dest-type->left
22282       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
22283       {
22284         75/jump-if-!= break/disp8
22285 $check-mu-copy-to-stmt:dest-is-deref2:
22286         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
22287       }
22288       89/<- %ebx 0/r32/eax
22289     }
22290     # if dest is a byte and src is not a literal, abort
22291     {
22292 $check-mu-copy-to-stmt:final-check-byte:
22293       (simple-mu-type? %ebx 8)  # byte => eax
22294       3d/compare-eax-and 0/imm32/false
22295       74/jump-if-= break/disp8
22296       (simple-mu-type? %ecx 0)  # literal => eax
22297       3d/compare-eax-and 0/imm32/false
22298       0f 84/jump-if-= $check-mu-copy-to-stmt:error-non-literal-to-byte/disp32
22299     }
22300     # if (src-type == dest-type) return
22301     (type-match? %ebx %ecx %edx)  # => eax
22302     3d/compare-eax-and 0/imm32
22303     0f 85/jump-if-!= $check-mu-copy-to-stmt:end/disp32
22304     # if dest is an addr and src is 0, return
22305     {
22306 $check-mu-copy-to-stmt:final-check-addr:
22307       (mu-addr-type? %ebx)  # => eax
22308       3d/compare-eax-and 0/imm32/false
22309       74/jump-if-= break/disp8
22310       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22311       (lookup *eax *(eax+4))  # Var-name Var-name => eax
22312       (string-equal? %eax "0")  # => eax
22313       3d/compare-eax-and 0/imm32/false
22314       74/jump-if-= break/disp8
22315       e9/jump $check-mu-copy-to-stmt:end/disp32
22316     }
22317     # if dest is an offset and src is 0, return
22318     {
22319 $check-mu-copy-to-stmt:final-check-offset:
22320       81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
22321       75/jump-if-!= break/disp8
22322       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
22323       (simple-mu-type? %eax 7)  # offset => eax
22324       3d/compare-eax-and 0/imm32/false
22325       74/jump-if-= break/disp8
22326       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22327       (lookup *eax *(eax+4))  # Var-name Var-name => eax
22328       (string-equal? %eax "0")  # => eax
22329       3d/compare-eax-and 0/imm32/false
22330       74/jump-if-= break/disp8
22331       e9/jump $check-mu-copy-to-stmt:end/disp32
22332     }
22333     # if dest is not number-like, abort
22334     (check-mu-numberlike-arg %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
22335 $check-mu-copy-to-stmt:end:
22336     # . reclaim locals
22337     81 0/subop/add %esp 0x6c/imm32
22338     # . restore registers
22339     5f/pop-to-edi
22340     5e/pop-to-esi
22341     5b/pop-to-ebx
22342     5a/pop-to-edx
22343     59/pop-to-ecx
22344     58/pop-to-eax
22345     # . epilogue
22346     89/<- %esp 5/r32/ebp
22347     5d/pop-to-ebp
22348     c3/return
22349 
22350 $check-mu-copy-to-stmt:error-incorrect-inouts:
22351     (write-buffered *(ebp+0x10) "fn ")
22352     8b/-> *(ebp+0xc) 0/r32/eax
22353     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22354     (write-buffered *(ebp+0x10) %eax)
22355     (write-buffered *(ebp+0x10) ": stmt 'copy-to' must have two inouts\n")
22356     (flush *(ebp+0x10))
22357     (stop *(ebp+0x14) 1)
22358     # never gets here
22359 
22360 $check-mu-copy-to-stmt:error-too-many-outputs:
22361     (write-buffered *(ebp+0x10) "fn ")
22362     8b/-> *(ebp+0xc) 0/r32/eax
22363     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22364     (write-buffered *(ebp+0x10) %eax)
22365     (write-buffered *(ebp+0x10) ": stmt 'copy-to' must not have any outputs\n")
22366     (flush *(ebp+0x10))
22367     (stop *(ebp+0x14) 1)
22368     # never gets here
22369 
22370 $check-mu-copy-to-stmt:error-src-not-literal-or-in-register:
22371     (write-buffered *(ebp+0x10) "fn ")
22372     8b/-> *(ebp+0xc) 0/r32/eax
22373     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22374     (write-buffered *(ebp+0x10) %eax)
22375     (write-buffered *(ebp+0x10) ": stmt copy-to: source (second inout) is in memory\n")
22376     (flush *(ebp+0x10))
22377     (stop *(ebp+0x14) 1)
22378     # never gets here
22379 
22380 $check-mu-copy-to-stmt:error-src-too-large:
22381     (write-buffered *(ebp+0x10) "fn ")
22382     8b/-> *(ebp+0xc) 0/r32/eax
22383     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22384     (write-buffered *(ebp+0x10) %eax)
22385     (write-buffered *(ebp+0x10) ": stmt copy-to: '")
22386     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22387     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22388     (write-buffered *(ebp+0x10) %eax)
22389     (write-buffered *(ebp+0x10) "' is too large to copy\n")
22390     (flush *(ebp+0x10))
22391     (stop *(ebp+0x14) 1)
22392     # never gets here
22393 
22394 $check-mu-copy-to-stmt:error-non-literal-to-byte:
22395     (write-buffered *(ebp+0x10) "fn ")
22396     8b/-> *(ebp+0xc) 0/r32/eax
22397     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22398     (write-buffered *(ebp+0x10) %eax)
22399     (write-buffered *(ebp+0x10) ": stmt copy-to: cannot copy non-literal to type byte; use copy-byte-to\n")
22400     (flush *(ebp+0x10))
22401     (stop *(ebp+0x14) 1)
22402     # never gets here
22403 
22404 check-mu-copy-byte-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
22405     # . prologue
22406     55/push-ebp
22407     89/<- %ebp 4/r32/esp
22408     # . save registers
22409     50/push-eax
22410     51/push-ecx
22411     52/push-edx
22412     56/push-esi
22413     57/push-edi
22414     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
22415     81 5/subop/subtract %esp 0x60/imm32
22416     68/push 0x60/imm32/size
22417     68/push 0/imm32/read
22418     68/push 0/imm32/write
22419     89/<- %edx 4/r32/esp
22420 $check-mu-copy-byte-stmt:get-output:
22421     # esi = stmt
22422     8b/-> *(ebp+8) 6/r32/esi
22423     # var output/edi: (addr stmt-var) = stmt->outputs
22424     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
22425     89/<- %edi 0/r32/eax
22426     # zero outputs
22427     3d/compare-eax-and 0/imm32
22428     0f 84/jump-if-= $check-mu-copy-byte-stmt:error-no-output/disp32
22429     # > 1 output
22430     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
22431     3d/compare-eax-and 0/imm32
22432     0f 85/jump-if-!= $check-mu-copy-byte-stmt:error-too-many-outputs/disp32
22433 $check-mu-copy-byte-stmt:get-inout:
22434     # var inout/esi: (addr stmt-var) = stmt->inouts
22435     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22436     89/<- %esi 0/r32/eax
22437     # zero inouts
22438     3d/compare-eax-and 0/imm32
22439     0f 84/jump-if-= $check-mu-copy-byte-stmt:error-no-inout/disp32
22440     # > 1 inout
22441     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
22442     3d/compare-eax-and 0/imm32
22443     0f 85/jump-if-!= $check-mu-copy-byte-stmt:error-too-many-inouts/disp32
22444 $check-mu-copy-byte-stmt:types:
22445     # if inout is not a scalar, abort
22446     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22447     (size-of %eax)  # => eax
22448     3d/compare-eax-and 4/imm32
22449     0f 8f/jump-if-> $check-mu-copy-byte-stmt:error-inout-too-large/disp32
22450     # var inout-type/ecx: (addr type-tree) = inout->value->type
22451     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22452     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22453     89/<- %ecx 0/r32/eax
22454 $check-mu-copy-byte-stmt:check-inout-deref:
22455     # if (inout->is-deref?) inout-type = inout-type->payload
22456     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
22457     3d/compare-eax-and 0/imm32/false
22458     {
22459       74/jump-if-= break/disp8
22460 $check-mu-copy-byte-stmt:inout-is-deref:
22461       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
22462       # if inout-type->right is null, t = inout-type->left
22463       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
22464       {
22465         75/jump-if-!= break/disp8
22466 $check-mu-copy-byte-stmt:inout-is-deref2:
22467         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
22468       }
22469       89/<- %ecx 0/r32/eax
22470     }
22471     # if output not in register, abort
22472     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22473     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
22474     3d/compare-eax-and 0/imm32
22475     0f 84/jump-if-= $check-mu-copy-byte-stmt:error-output-not-in-register/disp32
22476     # var output-type/eax: (addr type-tree) = output->value->type
22477     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22478     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22479     # if output is not of type byte, abort
22480     (simple-mu-type? %eax 8)  # byte => eax
22481     3d/compare-eax-and 0/imm32
22482     0f 84/jump-if-= $check-mu-copy-byte-stmt:error-invalid-output-type/disp32
22483 $check-mu-copy-byte-stmt:end:
22484     # . reclaim locals
22485     81 0/subop/add %esp 0x6c/imm32
22486     # . restore registers
22487     5f/pop-to-edi
22488     5e/pop-to-esi
22489     5a/pop-to-edx
22490     59/pop-to-ecx
22491     58/pop-to-eax
22492     # . epilogue
22493     89/<- %esp 5/r32/ebp
22494     5d/pop-to-ebp
22495     c3/return
22496 
22497 $check-mu-copy-byte-stmt:error-no-inout:
22498     (write-buffered *(ebp+0x10) "fn ")
22499     8b/-> *(ebp+0xc) 0/r32/eax
22500     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22501     (write-buffered *(ebp+0x10) %eax)
22502     (write-buffered *(ebp+0x10) ": stmt 'copy-byte' expects an inout\n")
22503     (flush *(ebp+0x10))
22504     (stop *(ebp+0x14) 1)
22505     # never gets here
22506 
22507 $check-mu-copy-byte-stmt:error-too-many-inouts:
22508     (write-buffered *(ebp+0x10) "fn ")
22509     8b/-> *(ebp+0xc) 0/r32/eax
22510     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22511     (write-buffered *(ebp+0x10) %eax)
22512     (write-buffered *(ebp+0x10) ": stmt 'copy-byte' must have just one inout\n")
22513     (flush *(ebp+0x10))
22514     (stop *(ebp+0x14) 1)
22515     # never gets here
22516 
22517 $check-mu-copy-byte-stmt:error-no-output:
22518     (write-buffered *(ebp+0x10) "fn ")
22519     8b/-> *(ebp+0xc) 0/r32/eax
22520     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22521     (write-buffered *(ebp+0x10) %eax)
22522     (write-buffered *(ebp+0x10) ": stmt 'copy-byte' expects an output\n")
22523     (flush *(ebp+0x10))
22524     (stop *(ebp+0x14) 1)
22525     # never gets here
22526 
22527 $check-mu-copy-byte-stmt:error-output-not-in-register:
22528     (write-buffered *(ebp+0x10) "fn ")
22529     8b/-> *(ebp+0xc) 0/r32/eax
22530     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22531     (write-buffered *(ebp+0x10) %eax)
22532     (write-buffered *(ebp+0x10) ": stmt copy-byte: output '")
22533     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22534     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22535     (write-buffered *(ebp+0x10) %eax)
22536     (write-buffered *(ebp+0x10) "' not in a register\n")
22537     (flush *(ebp+0x10))
22538     (stop *(ebp+0x14) 1)
22539     # never gets here
22540 
22541 $check-mu-copy-byte-stmt:error-too-many-outputs:
22542     (write-buffered *(ebp+0x10) "fn ")
22543     8b/-> *(ebp+0xc) 0/r32/eax
22544     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22545     (write-buffered *(ebp+0x10) %eax)
22546     (write-buffered *(ebp+0x10) ": stmt 'copy-byte' must have just one output\n")
22547     (flush *(ebp+0x10))
22548     (stop *(ebp+0x14) 1)
22549     # never gets here
22550 
22551 $check-mu-copy-byte-stmt:error-invalid-output-type:
22552     (write-buffered *(ebp+0x10) "fn ")
22553     8b/-> *(ebp+0xc) 0/r32/eax
22554     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22555     (write-buffered *(ebp+0x10) %eax)
22556     (write-buffered *(ebp+0x10) ": stmt 'copy-byte' must write to output of type byte\n")
22557     (flush *(ebp+0x10))
22558     (stop *(ebp+0x14) 1)
22559     # never gets here
22560 
22561 $check-mu-copy-byte-stmt:error-inout-too-large:
22562     (write-buffered *(ebp+0x10) "fn ")
22563     8b/-> *(ebp+0xc) 0/r32/eax
22564     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22565     (write-buffered *(ebp+0x10) %eax)
22566     (write-buffered *(ebp+0x10) ": stmt copy-byte: '")
22567     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22568     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22569     (write-buffered *(ebp+0x10) %eax)
22570     (write-buffered *(ebp+0x10) "' is too large to fit in a register\n")
22571     (flush *(ebp+0x10))
22572     (stop *(ebp+0x14) 1)
22573     # never gets here
22574 
22575 check-mu-copy-byte-to-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
22576     # . prologue
22577     55/push-ebp
22578     89/<- %ebp 4/r32/esp
22579     # . save registers
22580     50/push-eax
22581     52/push-edx
22582     53/push-ebx
22583     56/push-esi
22584     57/push-edi
22585     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
22586     81 5/subop/subtract %esp 0x60/imm32
22587     68/push 0x60/imm32/size
22588     68/push 0/imm32/read
22589     68/push 0/imm32/write
22590     89/<- %edx 4/r32/esp
22591     # esi = stmt
22592     8b/-> *(ebp+8) 6/r32/esi
22593 $check-mu-copy-byte-to-stmt:check-for-output:
22594     # if stmt->outputs abort
22595     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
22596     3d/compare-eax-and 0/imm32
22597     0f 85/jump-if-!= $check-mu-copy-byte-to-stmt:error-too-many-outputs/disp32
22598 $check-mu-copy-byte-to-stmt:get-dest:
22599     # var dest/edi: (addr stmt-var) = stmt->inouts
22600     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22601     89/<- %edi 0/r32/eax
22602     # zero inouts
22603     3d/compare-eax-and 0/imm32
22604     0f 84/jump-if-= $check-mu-copy-byte-to-stmt:error-incorrect-inouts/disp32
22605 $check-mu-copy-byte-to-stmt:get-src:
22606     # var src/esi: (addr stmt-var) = dest->next
22607     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
22608     89/<- %esi 0/r32/eax
22609     # 1 inout
22610     3d/compare-eax-and 0/imm32
22611     0f 84/jump-if-= $check-mu-copy-byte-to-stmt:error-incorrect-inouts/disp32
22612     # > 2 inouts
22613     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
22614     3d/compare-eax-and 0/imm32
22615     0f 85/jump-if-!= $check-mu-copy-byte-to-stmt:error-incorrect-inouts/disp32
22616 $check-mu-copy-byte-to-stmt:types:
22617     # if src is not a scalar, abort
22618     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22619     (size-of %eax)  # => eax
22620     3d/compare-eax-and 4/imm32
22621     0f 8f/jump-if-> $check-mu-copy-byte-to-stmt:error-src-too-large/disp32
22622     # if src not in register, abort
22623     {
22624       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22625       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
22626       3d/compare-eax-and 0/imm32
22627       75/jump-if-!= break/disp8
22628       e9/jump $check-mu-copy-byte-to-stmt:error-src-not-in-register/disp32
22629     }
22630     # var dest-type/ebx: (addr type-tree) = dest->value->type
22631     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22632     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22633     89/<- %ebx 0/r32/eax
22634     # if (dest->is-deref?) dest-type = dest-type->payload
22635 $check-mu-copy-byte-to-stmt:check-dest-deref:
22636     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
22637     3d/compare-eax-and 0/imm32/false
22638     {
22639       74/jump-if-= break/disp8
22640       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
22641 $check-mu-copy-byte-to-stmt:dest-is-deref:
22642       # if dest-type->right is null, dest-type = dest-type->left
22643       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
22644       {
22645         75/jump-if-!= break/disp8
22646 $check-mu-copy-byte-to-stmt:dest-is-deref2:
22647         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
22648       }
22649       89/<- %ebx 0/r32/eax
22650     }
22651     # if dest is not a byte, abort
22652     (simple-mu-type? %ebx 8)  # byte => eax
22653     3d/compare-eax-and 0/imm32/false
22654     0f 84/jump-if-= $check-mu-copy-byte-to-stmt:error-invalid-dest-type/disp32
22655 $check-mu-copy-byte-to-stmt:end:
22656     # . reclaim locals
22657     81 0/subop/add %esp 0x6c/imm32
22658     # . restore registers
22659     5f/pop-to-edi
22660     5e/pop-to-esi
22661     5b/pop-to-ebx
22662     5a/pop-to-edx
22663     58/pop-to-eax
22664     # . epilogue
22665     89/<- %esp 5/r32/ebp
22666     5d/pop-to-ebp
22667     c3/return
22668 
22669 $check-mu-copy-byte-to-stmt:error-incorrect-inouts:
22670     (write-buffered *(ebp+0x10) "fn ")
22671     8b/-> *(ebp+0xc) 0/r32/eax
22672     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22673     (write-buffered *(ebp+0x10) %eax)
22674     (write-buffered *(ebp+0x10) ": stmt 'copy-byte-to' must have two inouts\n")
22675     (flush *(ebp+0x10))
22676     (stop *(ebp+0x14) 1)
22677     # never gets here
22678 
22679 $check-mu-copy-byte-to-stmt:error-too-many-outputs:
22680     (write-buffered *(ebp+0x10) "fn ")
22681     8b/-> *(ebp+0xc) 0/r32/eax
22682     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22683     (write-buffered *(ebp+0x10) %eax)
22684     (write-buffered *(ebp+0x10) ": stmt 'copy-byte-to' must not have any outputs\n")
22685     (flush *(ebp+0x10))
22686     (stop *(ebp+0x14) 1)
22687     # never gets here
22688 
22689 $check-mu-copy-byte-to-stmt:error-src-not-in-register:
22690     (write-buffered *(ebp+0x10) "fn ")
22691     8b/-> *(ebp+0xc) 0/r32/eax
22692     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22693     (write-buffered *(ebp+0x10) %eax)
22694     (write-buffered *(ebp+0x10) ": stmt copy-byte-to: source (second inout) must be in a register\n")
22695     (flush *(ebp+0x10))
22696     (stop *(ebp+0x14) 1)
22697     # never gets here
22698 
22699 $check-mu-copy-byte-to-stmt:error-invalid-dest-type:
22700     (write-buffered *(ebp+0x10) "fn ")
22701     8b/-> *(ebp+0xc) 0/r32/eax
22702     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22703     (write-buffered *(ebp+0x10) %eax)
22704     (write-buffered *(ebp+0x10) ": stmt copy-byte-to: '")
22705     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22706     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22707     (write-buffered *(ebp+0x10) %eax)
22708     (write-buffered *(ebp+0x10) "' must be a byte\n")
22709     (flush *(ebp+0x10))
22710     (stop *(ebp+0x14) 1)
22711     # never gets here
22712 
22713 $check-mu-copy-byte-to-stmt:error-src-too-large:
22714     (write-buffered *(ebp+0x10) "fn ")
22715     8b/-> *(ebp+0xc) 0/r32/eax
22716     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22717     (write-buffered *(ebp+0x10) %eax)
22718     (write-buffered *(ebp+0x10) ": stmt copy-byte-to: '")
22719     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22720     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22721     (write-buffered *(ebp+0x10) %eax)
22722     (write-buffered *(ebp+0x10) "' is too large to copy\n")
22723     (flush *(ebp+0x10))
22724     (stop *(ebp+0x14) 1)
22725     # never gets here
22726 
22727 check-mu-compare-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
22728     # . prologue
22729     55/push-ebp
22730     89/<- %ebp 4/r32/esp
22731     # . save registers
22732     50/push-eax
22733     51/push-ecx
22734     52/push-edx
22735     53/push-ebx
22736     56/push-esi
22737     57/push-edi
22738     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
22739     81 5/subop/subtract %esp 0x60/imm32
22740     68/push 0x60/imm32/size
22741     68/push 0/imm32/read
22742     68/push 0/imm32/write
22743     89/<- %edx 4/r32/esp
22744     # esi = stmt
22745     8b/-> *(ebp+8) 6/r32/esi
22746 $check-mu-compare-stmt:check-for-output:
22747     # if stmt->outputs abort
22748     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
22749     3d/compare-eax-and 0/imm32
22750     0f 85/jump-if-!= $check-mu-compare-stmt:error-too-many-outputs/disp32
22751 $check-mu-compare-stmt:get-left:
22752     # var left/edi: (addr stmt-var) = stmt->inouts
22753     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22754     89/<- %edi 0/r32/eax
22755     # zero inouts
22756     3d/compare-eax-and 0/imm32
22757     0f 84/jump-if-= $check-mu-compare-stmt:error-incorrect-inouts/disp32
22758 $check-mu-compare-stmt:get-right:
22759     # var right/esi: (addr stmt-var) = left->next
22760     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
22761     89/<- %esi 0/r32/eax
22762     # 1 inout
22763     3d/compare-eax-and 0/imm32
22764     0f 84/jump-if-= $check-mu-compare-stmt:error-incorrect-inouts/disp32
22765     # > 2 inouts
22766     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
22767     3d/compare-eax-and 0/imm32
22768     0f 85/jump-if-!= $check-mu-compare-stmt:error-incorrect-inouts/disp32
22769     # if both inouts are in memory, abort
22770     {
22771 $check-mu-compare-stmt:both-in-mem:
22772       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22773       (lookup *(eax+0x8) *(eax+0xc))  # Var-type Var-type => eax
22774       (simple-mu-type? %eax 0)  # => eax
22775       3d/compare-eax-and 0/imm32
22776       0f 85/jump-if-!= break/disp32
22777       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22778       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
22779       3d/compare-eax-and 0/imm32
22780       75/jump-if-!= break/disp8
22781       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22782       (lookup *(eax+0x8) *(eax+0xc))  # Var-type Var-type => eax
22783       (simple-mu-type? %eax 0)  # => eax
22784       3d/compare-eax-and 0/imm32
22785       75/jump-if-!= break/disp8
22786       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22787       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
22788       3d/compare-eax-and 0/imm32
22789       75/jump-if-!= break/disp8
22790       e9/jump $check-mu-compare-stmt:error-both-in-memory/disp32
22791     }
22792 $check-mu-compare-stmt:types:
22793     # var right-type/ecx: (addr type-tree) = right->value->type
22794     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22795     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22796     89/<- %ecx 0/r32/eax
22797     # if (right->is-deref?) right-type = right-type->payload
22798     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
22799     3d/compare-eax-and 0/imm32/false
22800     {
22801       74/jump-if-= break/disp8
22802       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
22803       # if right-type->right is null, right-type = right-type->left
22804       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
22805       {
22806         75/jump-if-!= break/disp8
22807         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
22808       }
22809       89/<- %ecx 0/r32/eax
22810     }
22811     # if right-type is a literal string, abort
22812     (simple-mu-type? %ecx 0x10)  # string-literal => eax
22813     3d/compare-eax-and 0/imm32/false
22814     0f 85/jump-if-!= $check-mu-compare-stmt:error-right-string-literal/disp32
22815     # if right is not a scalar, abort
22816     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22817     (size-of %eax)  # => eax
22818     3d/compare-eax-and 4/imm32
22819     0f 8f/jump-if-> $check-mu-compare-stmt:error-right-too-large/disp32
22820     # if left is not a scalar, abort
22821     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22822     (size-of %eax)  # => eax
22823     3d/compare-eax-and 4/imm32
22824     0f 8f/jump-if-> $check-mu-compare-stmt:error-left-too-large/disp32
22825     # var left-type/ebx: (addr type-tree) = left->value->type
22826     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22827     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22828     89/<- %ebx 0/r32/eax
22829     # if (left->is-deref?) left-type = left-type->payload
22830     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
22831     3d/compare-eax-and 0/imm32/false
22832     {
22833       74/jump-if-= break/disp8
22834       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
22835       # if left-type->right is null, left-type = left-type->left
22836       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
22837       {
22838         75/jump-if-!= break/disp8
22839         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
22840       }
22841       89/<- %ebx 0/r32/eax
22842     }
22843     # if (left-type == right-type) return
22844     (type-match? %ebx %ecx %edx)  # => eax
22845     3d/compare-eax-and 0/imm32
22846     0f 85/jump-if-!= $check-mu-compare-stmt:end/disp32
22847     # if left is an addr and right is 0, return
22848     {
22849       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22850       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22851       (mu-addr-type? %eax)  # => eax
22852       3d/compare-eax-and 0/imm32/false
22853       74/jump-if-= break/disp8
22854       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22855       (lookup *eax *(eax+4))  # Var-name Var-name => eax
22856       (string-equal? %eax "0")  # => eax
22857       3d/compare-eax-and 0/imm32/false
22858       74/jump-if-= break/disp8
22859       eb/jump $check-mu-compare-stmt:end/disp8
22860     }
22861     # if left is not number-like, abort
22862     (check-mu-numberlike-arg %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
22863 $check-mu-compare-stmt:end:
22864     # . reclaim locals
22865     81 0/subop/add %esp 0x6c/imm32
22866     # . restore registers
22867     5f/pop-to-edi
22868     5e/pop-to-esi
22869     5b/pop-to-ebx
22870     5a/pop-to-edx
22871     59/pop-to-ecx
22872     58/pop-to-eax
22873     # . epilogue
22874     89/<- %esp 5/r32/ebp
22875     5d/pop-to-ebp
22876     c3/return
22877 
22878 $check-mu-compare-stmt:error-incorrect-inouts:
22879     (write-buffered *(ebp+0x10) "fn ")
22880     8b/-> *(ebp+0xc) 0/r32/eax
22881     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22882     (write-buffered *(ebp+0x10) %eax)
22883     (write-buffered *(ebp+0x10) ": stmt 'compare' must have two inouts\n")
22884     (flush *(ebp+0x10))
22885     (stop *(ebp+0x14) 1)
22886     # never gets here
22887 
22888 $check-mu-compare-stmt:error-too-many-outputs:
22889     (write-buffered *(ebp+0x10) "fn ")
22890     8b/-> *(ebp+0xc) 0/r32/eax
22891     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22892     (write-buffered *(ebp+0x10) %eax)
22893     (write-buffered *(ebp+0x10) ": stmt 'compare' must not have any outputs\n")
22894     (flush *(ebp+0x10))
22895     (stop *(ebp+0x14) 1)
22896     # never gets here
22897 
22898 $check-mu-compare-stmt:error-both-in-memory:
22899     (write-buffered *(ebp+0x10) "fn ")
22900     8b/-> *(ebp+0xc) 0/r32/eax
22901     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22902     (write-buffered *(ebp+0x10) %eax)
22903     (write-buffered *(ebp+0x10) ": stmt compare: both inouts are in memory\n")
22904     (flush *(ebp+0x10))
22905     (stop *(ebp+0x14) 1)
22906     # never gets here
22907 
22908 $check-mu-compare-stmt:error-left-too-large:
22909     (write-buffered *(ebp+0x10) "fn ")
22910     8b/-> *(ebp+0xc) 0/r32/eax
22911     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22912     (write-buffered *(ebp+0x10) %eax)
22913     (write-buffered *(ebp+0x10) ": stmt compare: '")
22914     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22915     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22916     (write-buffered *(ebp+0x10) %eax)
22917     (write-buffered *(ebp+0x10) "' is too large to compare\n")
22918     (flush *(ebp+0x10))
22919     (stop *(ebp+0x14) 1)
22920     # never gets here
22921 
22922 $check-mu-compare-stmt:error-right-too-large:
22923     (write-buffered *(ebp+0x10) "fn ")
22924     8b/-> *(ebp+0xc) 0/r32/eax
22925     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22926     (write-buffered *(ebp+0x10) %eax)
22927     (write-buffered *(ebp+0x10) ": stmt compare: '")
22928     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22929     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22930     (write-buffered *(ebp+0x10) %eax)
22931     (write-buffered *(ebp+0x10) "' is too large to compare\n")
22932     (flush *(ebp+0x10))
22933     (stop *(ebp+0x14) 1)
22934     # never gets here
22935 
22936 $check-mu-compare-stmt:error-right-string-literal:
22937     (write-buffered *(ebp+0x10) "fn ")
22938     8b/-> *(ebp+0xc) 0/r32/eax
22939     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22940     (write-buffered *(ebp+0x10) %eax)
22941     (write-buffered *(ebp+0x10) ": stmt compare: string literal ")
22942     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22943     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22944     (write-buffered *(ebp+0x10) %eax)
22945     (write-buffered *(ebp+0x10) " is not supported; use the string-equal? function\n")
22946     (flush *(ebp+0x10))
22947     (stop *(ebp+0x14) 1)
22948     # never gets here
22949 
22950 check-mu-address-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
22951     # . prologue
22952     55/push-ebp
22953     89/<- %ebp 4/r32/esp
22954     # . save registers
22955     50/push-eax
22956     51/push-ecx
22957     52/push-edx
22958     56/push-esi
22959     57/push-edi
22960 $check-mu-address-stmt:get-output:
22961     # esi = stmt
22962     8b/-> *(ebp+8) 6/r32/esi
22963     # var output/edi: (addr stmt-var) = stmt->outputs
22964     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
22965     89/<- %edi 0/r32/eax
22966     # zero outputs
22967     3d/compare-eax-and 0/imm32
22968     0f 84/jump-if-= $check-mu-address-stmt:error-no-output/disp32
22969     # > 1 output
22970     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
22971     3d/compare-eax-and 0/imm32
22972     0f 85/jump-if-!= $check-mu-address-stmt:error-too-many-outputs/disp32
22973 $check-mu-address-stmt:get-inout:
22974     # var inout/esi: (addr stmt-var) = stmt->inouts
22975     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22976     89/<- %esi 0/r32/eax
22977     # zero inouts
22978     3d/compare-eax-and 0/imm32
22979     0f 84/jump-if-= $check-mu-address-stmt:error-no-inout/disp32
22980     # > 1 inout
22981     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
22982     3d/compare-eax-and 0/imm32
22983     0f 85/jump-if-!= $check-mu-address-stmt:error-too-many-inouts/disp32
22984 $check-mu-address-stmt:types:
22985     # if output not in register, abort
22986     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22987     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
22988     3d/compare-eax-and 0/imm32
22989     0f 84/jump-if-= $check-mu-address-stmt:error-output-not-in-register/disp32
22990     # var output-type/edx: (addr type-tree) = output->value->type
22991     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22992     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22993     89/<- %edx 0/r32/eax
22994     # if output-type not an addr, abort
22995     (mu-addr-type? %edx)  # => eax
22996     3d/compare-eax-and 0/imm32/false
22997     0f 84/jump-if-= $check-mu-address-stmt:error-output-not-address/disp32
22998     # output-type = output-type->right
22999     (lookup *(edx+0xc) *(edx+0x10))  # Type-tree-right Type-tree-right => eax
23000     # if output-type->right is null, output-type = output-type->left
23001     81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
23002     {
23003       75/jump-if-!= break/disp8
23004       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23005     }
23006     89/<- %edx 0/r32/eax
23007     # var inout-type/ecx: (addr type-tree) = inout->value->type
23008     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
23009     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
23010     89/<- %ecx 0/r32/eax
23011     # if (inout->is-deref?) inout-type = inout-type->payload
23012     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
23013     3d/compare-eax-and 0/imm32/false
23014     {
23015       74/jump-if-= break/disp8
23016       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
23017       # if inout-type->right is null, t = inout-type->left
23018       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
23019       {
23020         75/jump-if-!= break/disp8
23021         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23022       }
23023       89/<- %ecx 0/r32/eax
23024     }
23025     # if (inout-type != output-type) abort
23026     (type-equal-ignoring-capacity? %edx %ecx)  # => eax
23027     3d/compare-eax-and 0/imm32
23028     0f 84/jump-if-= $check-mu-address-stmt:error-type-mismatch/disp32
23029 $check-mu-address-stmt:end:
23030     # . restore registers
23031     5f/pop-to-edi
23032     5e/pop-to-esi
23033     5a/pop-to-edx
23034     59/pop-to-ecx
23035     58/pop-to-eax
23036     # . epilogue
23037     89/<- %esp 5/r32/ebp
23038     5d/pop-to-ebp
23039     c3/return
23040 
23041 $check-mu-address-stmt:error-no-inout:
23042     (write-buffered *(ebp+0x10) "fn ")
23043     8b/-> *(ebp+0xc) 0/r32/eax
23044     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23045     (write-buffered *(ebp+0x10) %eax)
23046     (write-buffered *(ebp+0x10) ": stmt 'address' expects an inout\n")
23047     (flush *(ebp+0x10))
23048     (stop *(ebp+0x14) 1)
23049     # never gets here
23050 
23051 $check-mu-address-stmt:error-too-many-inouts:
23052     (write-buffered *(ebp+0x10) "fn ")
23053     8b/-> *(ebp+0xc) 0/r32/eax
23054     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23055     (write-buffered *(ebp+0x10) %eax)
23056     (write-buffered *(ebp+0x10) ": stmt 'address' must have just one inout\n")
23057     (flush *(ebp+0x10))
23058     (stop *(ebp+0x14) 1)
23059     # never gets here
23060 
23061 $check-mu-address-stmt:error-no-output:
23062     (write-buffered *(ebp+0x10) "fn ")
23063     8b/-> *(ebp+0xc) 0/r32/eax
23064     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23065     (write-buffered *(ebp+0x10) %eax)
23066     (write-buffered *(ebp+0x10) ": stmt 'address' expects an output\n")
23067     (flush *(ebp+0x10))
23068     (stop *(ebp+0x14) 1)
23069     # never gets here
23070 
23071 $check-mu-address-stmt:error-output-not-in-register:
23072     (write-buffered *(ebp+0x10) "fn ")
23073     8b/-> *(ebp+0xc) 0/r32/eax
23074     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23075     (write-buffered *(ebp+0x10) %eax)
23076     (write-buffered *(ebp+0x10) ": stmt address: output '")
23077     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
23078     (lookup *eax *(eax+4))  # Var-name Var-name => eax
23079     (write-buffered *(ebp+0x10) %eax)
23080     (write-buffered *(ebp+0x10) "' not in a register\n")
23081     (flush *(ebp+0x10))
23082     (stop *(ebp+0x14) 1)
23083     # never gets here
23084 
23085 $check-mu-address-stmt:error-too-many-outputs:
23086     (write-buffered *(ebp+0x10) "fn ")
23087     8b/-> *(ebp+0xc) 0/r32/eax
23088     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23089     (write-buffered *(ebp+0x10) %eax)
23090     (write-buffered *(ebp+0x10) ": stmt 'address' must have just one output\n")
23091     (flush *(ebp+0x10))
23092     (stop *(ebp+0x14) 1)
23093     # never gets here
23094 
23095 $check-mu-address-stmt:error-output-not-address:
23096     (write-buffered *(ebp+0x10) "fn ")
23097     8b/-> *(ebp+0xc) 0/r32/eax
23098     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23099     (write-buffered *(ebp+0x10) %eax)
23100     (write-buffered *(ebp+0x10) ": stmt address: output '")
23101     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
23102     (lookup *eax *(eax+4))  # Var-name Var-name => eax
23103     (write-buffered *(ebp+0x10) %eax)
23104     (write-buffered *(ebp+0x10) "' is not an addr\n")
23105     (flush *(ebp+0x10))
23106     (stop *(ebp+0x14) 1)
23107     # never gets here
23108 
23109 $check-mu-address-stmt:error-type-mismatch:
23110     (write-buffered *(ebp+0x10) "fn ")
23111     8b/-> *(ebp+0xc) 0/r32/eax
23112     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23113     (write-buffered *(ebp+0x10) %eax)
23114     (write-buffered *(ebp+0x10) ": stmt address: output '")
23115     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
23116     (lookup *eax *(eax+4))  # Var-name Var-name => eax
23117     (write-buffered *(ebp+0x10) %eax)
23118     (write-buffered *(ebp+0x10) "' cannot hold address of '")
23119     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
23120     (lookup *eax *(eax+4))  # Var-name Var-name => eax
23121     (write-buffered *(ebp+0x10) %eax)
23122     (write-buffered *(ebp+0x10) "'\n")
23123     (flush *(ebp+0x10))
23124     (stop *(ebp+0x14) 1)
23125     # never gets here
23126 
23127 type-equal-ignoring-capacity?:  # a: (addr type-tree), b: (addr type-tree) -> result/eax: boolean
23128     # . prologue
23129     55/push-ebp
23130     89/<- %ebp 4/r32/esp
23131     # . save registers
23132     51/push-ecx
23133     52/push-edx
23134     53/push-ebx
23135     # var curr-a/ecx: (addr type-tree) = a
23136     8b/-> *(ebp+8) 1/r32/ecx
23137     # var curr-b/ebx: (addr type-tree) = b
23138     8b/-> *(ebp+0xc) 3/r32/ebx
23139     # if (curr-a->is-atom?) fall back to regular equality
23140     81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
23141     0f 85/jump-if-!= $type-equal-ignoring-capacity?:base-case/disp32
23142     # if (curr-a->left != curr-b->left) return false
23143     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
23144     89/<- %edx 0/r32/eax
23145     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
23146     (type-equal? %edx %eax)  # => eax
23147     3d/compare-eax-and 0/imm32/false
23148     0f 84/jump-if-= $type-equal-ignoring-capacity?:end/disp32  # eax switches meaning
23149     # if (curr-a->left == "array") curr-a = curr-a->element-type
23150     {
23151       (mu-array? %edx)  # => eax
23152       3d/compare-eax-and 0/imm32/false
23153       75/jump-if-!= break/disp8
23154 $type-equal-ignoring-capacity?:array:
23155       # curr-a = curr-a->right->left
23156       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
23157       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23158       89/<- %ecx 0/r32/eax
23159       # curr-b = curr-b->right->left
23160       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
23161       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23162       89/<- %ebx 0/r32/eax
23163       eb/jump $type-equal-ignoring-capacity?:base-case/disp8
23164     }
23165     # if (curr-a->left == "stream") curr-a = curr-a->element-type
23166     {
23167       (mu-stream? %edx)  # => eax
23168       3d/compare-eax-and 0/imm32/false
23169       75/jump-if-!= break/disp8
23170 $type-equal-ignoring-capacity?:stream:
23171       # curr-a = curr-a->right->left
23172       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
23173       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23174       89/<- %ecx 0/r32/eax
23175       # curr-b = curr-b->right->left
23176       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
23177       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23178       89/<- %ebx 0/r32/eax
23179       eb/jump $type-equal-ignoring-capacity?:base-case/disp8
23180     }
23181 $type-equal-ignoring-capacity?:base-case:
23182     # return type-equal?(curr-a, curr-b)
23183     (type-equal? %ecx %ebx)  # => eax
23184 $type-equal-ignoring-capacity?:end:
23185     # . restore registers
23186     5b/pop-to-ebx
23187     5a/pop-to-edx
23188     59/pop-to-ecx
23189     # . epilogue
23190     89/<- %esp 5/r32/ebp
23191     5d/pop-to-ebp
23192     c3/return
23193 
23194 check-mu-return-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
23195     # . prologue
23196     55/push-ebp
23197     89/<- %ebp 4/r32/esp
23198     # . save registers
23199     50/push-eax
23200     51/push-ecx
23201     52/push-edx
23202     53/push-ebx
23203     56/push-esi
23204     57/push-edi
23205     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
23206     81 5/subop/subtract %esp 0x60/imm32
23207     68/push 0x60/imm32/size
23208     68/push 0/imm32/read
23209     68/push 0/imm32/write
23210     89/<- %edx 4/r32/esp
23211     # var template/esi: (addr list var) = fn->outputs
23212     8b/-> *(ebp+0xc) 0/r32/eax
23213     (lookup *(eax+0x10) *(eax+0x14))  # Function-outputs Function-outputs => eax
23214     89/<- %esi 0/r32/eax
23215     # var curr-template/ebx: (addr list var) = fn->outputs
23216     89/<- %ebx 0/r32/eax
23217     # var curr/edi: (addr stmt-var) = stmt->inouts
23218     8b/-> *(ebp+8) 0/r32/eax
23219     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23220     89/<- %edi 0/r32/eax
23221     {
23222       # if template is null, break
23223       81 7/subop/compare %ebx 0/imm32
23224       0f 84/jump-if-= break/disp32
23225       # if curr is null, abort
23226       81 7/subop/compare %edi 0/imm32
23227       0f 84/jump-if-= $check-mu-return-stmt:error-too-few-inouts/disp32
23228       # var template-type/ecx: (addr type-tree) = template->value->type
23229       (lookup *ebx *(ebx+4))  # List-value List-value => eax
23230       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
23231       89/<- %ecx 0/r32/eax
23232       # var curr-type/eax: (addr type-tree) = curr->value->type
23233       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
23234       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
23235       # if (curr->is-deref?) curr-type = payload of curr-type
23236       81 7/subop/compare *(edi+0x10) 0/imm32/false  # Stmt-var-is-deref
23237       {
23238         74/jump-if-= break/disp8
23239         (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
23240         # if t->right is null, t = t->left
23241         81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
23242         75/jump-if-!= break/disp8
23243         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23244       }
23245       # if curr-type is literal and template-type is float, abort
23246       50/push-eax
23247       {
23248         (simple-mu-type? %eax 0)  # literal => eax
23249         3d/compare-eax-and 0/imm32/false
23250         74/jump-if-= break/disp8
23251         (simple-mu-type? %ecx 0xf)  # float => eax
23252         3d/compare-eax-and 0/imm32/false
23253         0f 85/jump-if-!= $check-mu-return-stmt:error-literal-to-float/disp32
23254       }
23255       58/pop-to-eax
23256       # if (curr-type != template-type) abort
23257       (type-match? %ecx %eax %edx)  # => eax
23258       3d/compare-eax-and 0/imm32/false
23259       0f 84/jump-if-= $check-mu-return-stmt:error1/disp32
23260       # if register-within-list-with-conflict?(curr, original template, curr-template, stmt) abort
23261       (register-within-list-with-conflict? %edi %esi %ebx *(ebp+8))  # => eax
23262       3d/compare-eax-and 0/imm32/false
23263       0f 85/jump-if-!= $check-mu-return-stmt:error2/disp32
23264       # template = template->next
23265       (lookup *(ebx+8) *(ebx+0xc))  # List-next List-next => eax
23266       89/<- %ebx 0/r32/eax
23267       # curr = curr->next
23268       (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
23269       89/<- %edi 0/r32/eax
23270       #
23271       e9/jump loop/disp32
23272     }
23273     # if curr is not null, abort
23274     81 7/subop/compare %edi 0/imm32
23275     0f 85/jump-if-!= $check-mu-return-stmt:error-too-many-inouts/disp32
23276 $check-mu-return-stmt:end:
23277     # . reclaim locals
23278     81 0/subop/add %esp 0x6c/imm32
23279     # . restore registers
23280     5f/pop-to-edi
23281     5e/pop-to-esi
23282     5b/pop-to-ebx
23283     5a/pop-to-edx
23284     59/pop-to-ecx
23285     58/pop-to-eax
23286     # . epilogue
23287     89/<- %esp 5/r32/ebp
23288     5d/pop-to-ebp
23289     c3/return
23290 
23291 $check-mu-return-stmt:error1:
23292     (write-buffered *(ebp+0x10) "fn ")
23293     8b/-> *(ebp+0xc) 0/r32/eax
23294     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23295     (write-buffered *(ebp+0x10) %eax)
23296     (write-buffered *(ebp+0x10) ": return: '")
23297     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
23298     (lookup *eax *(eax+4))  # Var-name Var-name => eax
23299     (write-buffered *(ebp+0x10) %eax)
23300     (write-buffered *(ebp+0x10) "' has the wrong type\n")
23301     (flush *(ebp+0x10))
23302     (stop *(ebp+0x14) 1)
23303     # never gets here
23304 
23305 $check-mu-return-stmt:error2:
23306     (write-buffered *(ebp+0x10) "fn ")
23307     8b/-> *(ebp+0xc) 0/r32/eax
23308     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23309     (write-buffered *(ebp+0x10) %eax)
23310     (write-buffered *(ebp+0x10) ": return: '")
23311     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
23312     (lookup *eax *(eax+4))  # Var-name Var-name => eax
23313     (write-buffered *(ebp+0x10) %eax)
23314     (write-buffered *(ebp+0x10) "' is no longer available\n")
23315     (flush *(ebp+0x10))
23316     (stop *(ebp+0x14) 1)
23317     # never gets here
23318 
23319 $check-mu-return-stmt:error-literal-to-float:
23320     (write-buffered *(ebp+0x10) "fn ")
23321     8b/-> *(ebp+0xc) 0/r32/eax
23322     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23323     (write-buffered *(ebp+0x10) %eax)
23324     (write-buffered *(ebp+0x10) ": return: cannot copy literal '")
23325     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
23326     (lookup *eax *(eax+4))  # Var-name Var-name => eax
23327     (write-buffered *(ebp+0x10) %eax)
23328     (write-buffered *(ebp+0x10) "' to float\n")
23329     (flush *(ebp+0x10))
23330     (stop *(ebp+0x14) 1)
23331     # never gets here
23332 
23333 $check-mu-return-stmt:error-too-few-inouts:
23334     (write-buffered *(ebp+0x10) "fn ")
23335     8b/-> *(ebp+0xc) 0/r32/eax
23336     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23337     (write-buffered *(ebp+0x10) %eax)
23338     (write-buffered *(ebp+0x10) ": return: too few inouts\n")
23339     (flush *(ebp+0x10))
23340     (stop *(ebp+0x14) 1)
23341     # never gets here
23342 
23343 $check-mu-return-stmt:error-too-many-inouts:
23344     (write-buffered *(ebp+0x10) "fn ")
23345     8b/-> *(ebp+0xc) 0/r32/eax
23346     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23347     (write-buffered *(ebp+0x10) %eax)
23348     (write-buffered *(ebp+0x10) ": return: too many inouts\n")
23349     (flush *(ebp+0x10))
23350     (stop *(ebp+0x14) 1)
23351     # never gets here
23352 
23353 check-all-unique-registers:  # outputs: (addr list var), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
23354     # . prologue
23355     55/push-ebp
23356     89/<- %ebp 4/r32/esp
23357     # . save registers
23358     50/push-eax
23359     51/push-ecx
23360     56/push-esi
23361     # var table/esi: (addr table (handle array byte) int 8)
23362     81 5/subop/subtract %esp 0x60/imm32
23363     68/push 0x60/imm32/size
23364     68/push 0/imm32/read
23365     68/push 0/imm32/write
23366     89/<- %esi 4/r32/esp
23367     # var curr/ecx: (addr list var) = outputs
23368     8b/-> *(ebp+8) 1/r32/ecx
23369     {
23370       # if (curr == 0) break
23371       81 7/subop/compare %ecx 0/imm32
23372       0f 84/jump-if-= break/disp32
23373       # var reg/eax: (addr array byte) = curr->value->register  # guaranteed to exist
23374       (lookup *ecx *(ecx+4))  # List-value List-value => eax
23375       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
23376       # if reg exists in table, abort
23377       (maybe-get %esi %eax 0xc)  # => eax
23378       3d/compare-eax-and 0/imm32
23379       0f 85/jump-if-!= $check-all-unique-registers:abort/disp32
23380       # insert reg in table
23381       (lookup *ecx *(ecx+4))  # List-value List-value => eax
23382       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
23383       (get-or-insert %esi %eax 0xc Heap)
23384       # curr = curr->next
23385       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
23386       89/<- %ecx 0/r32/eax
23387       e9/jump loop/disp32
23388     }
23389 $check-all-unique-registers:end:
23390     # . reclaim locals
23391     81 0/subop/add %esp 0x6c/imm32
23392     # . restore registers
23393     5e/pop-to-esi
23394     59/pop-to-ecx
23395     58/pop-to-eax
23396     # . epilogue
23397     89/<- %esp 5/r32/ebp
23398     5d/pop-to-ebp
23399     c3/return
23400 
23401 $check-all-unique-registers:abort:
23402     (write-buffered *(ebp+0x10) "fn ")
23403     8b/-> *(ebp+0xc) 0/r32/eax
23404     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23405     (write-buffered *(ebp+0x10) %eax)
23406     (write-buffered *(ebp+0x10) ": outputs must be in unique registers\n")
23407     (flush *(ebp+0x10))
23408     (stop *(ebp+0x14) 1)
23409     # never gets here
23410 
23411 # return false if s's register is not between start (inclusive) and end (exclusive)
23412 # return false if the positionally corresponding register in stmt->inouts (where s comes from) is also s's register
23413 # otherwise return true
23414 register-within-list-with-conflict?:  # s: (addr stmt-var), start: (addr list var), end: (addr list var), stmt: (addr stmt) -> result/eax: boolean
23415     # . prologue
23416     55/push-ebp
23417     89/<- %ebp 4/r32/esp
23418     # . save registers
23419     51/push-ecx
23420     52/push-edx
23421     53/push-ebx
23422     56/push-esi
23423     57/push-edi
23424     # var target/ebx: (addr array byte) = s->value->register
23425     8b/-> *(ebp+8) 0/r32/eax
23426     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
23427     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
23428 #?     (write-buffered Stderr "AA: ")
23429 #?     (write-buffered Stderr %eax)
23430 #?     (write-buffered Stderr Newline)
23431 #?     (flush Stderr)
23432     # if (var->register == 0) return false
23433     3d/compare-eax-and 0/imm32
23434     0f 84/jump-if-= $register-within-list-with-conflict?:end/disp32  # eax turns into result
23435     89/<- %ebx 0/r32/eax
23436     # var curr/ecx: (addr list var) = start
23437     8b/-> *(ebp+0xc) 1/r32/ecx
23438     # edx = end
23439     8b/-> *(ebp+0x10) 2/r32/edx
23440     {
23441       # if (curr == 0) break
23442       81 7/subop/compare %edi 0/imm32
23443       0f 84/jump-if-= break/disp32
23444       # if (curr == end) break
23445       39/compare %ecx 2/r32/edx
23446       0f 84/jump-if-= break/disp32
23447       # var curr-reg/eax: (addr array byte) = curr->value->register
23448       (lookup *ecx *(ecx+4))  # List-value List-value => eax
23449       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
23450       # if (curr-reg == 0) continue
23451       3d/compare-eax-and 0/imm32
23452       74/jump-if-= $register-within-list-with-conflict?:continue/disp8
23453       # if (curr-reg == target) check for conflict
23454       (string-equal? %eax %ebx)  # => eax
23455       3d/compare-eax-and 0/imm32/false
23456       {
23457         74/jump-if-= break/disp8
23458 #?         (write-buffered Stderr "conflict?\n")
23459 #?         (flush Stderr)
23460         # var return-inouts/eax: (addr stmt-var) = stmt->inouts
23461         8b/-> *(ebp+0x14) 0/r32/eax
23462         (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23463         (register-conflict? %ebx %eax *(ebp+0xc))  # => eax
23464         eb/jump $register-within-list-with-conflict?:end/disp8
23465       }
23466 $register-within-list-with-conflict?:continue:
23467       # curr = curr->next
23468       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
23469       89/<- %ecx 0/r32/eax
23470       e9/jump loop/disp32
23471     }
23472     # return false
23473     b8/copy-to-eax 0/imm32/false
23474 $register-within-list-with-conflict?:end:
23475     # . restore registers
23476     5f/pop-to-edi
23477     5e/pop-to-esi
23478     5b/pop-to-ebx
23479     5a/pop-to-edx
23480     59/pop-to-ecx
23481     # . epilogue
23482     89/<- %esp 5/r32/ebp
23483     5d/pop-to-ebp
23484     c3/return
23485 
23486 # At the first occurrence of register 'reg' in fn-outputs,
23487 # check if the corresponding element of return-inouts has a different register.
23488 # This hacky helper is intended to be called in one specific place. Don't
23489 # reuse it as is.
23490 register-conflict?:  # reg: (addr array byte), return-inouts: (addr stmt-var), fn-outputs: (addr list var) => result/eax: boolean
23491     # . prologue
23492     55/push-ebp
23493     89/<- %ebp 4/r32/esp
23494     # . save registers
23495     51/push-ecx
23496     52/push-edx
23497     53/push-ebx
23498     56/push-esi
23499     57/push-edi
23500 #?     (write-buffered Stderr "BB: ")
23501 #?     (write-buffered Stderr *(ebp+8))
23502 #?     (write-buffered Stderr Newline)
23503 #?     (flush Stderr)
23504     # var curr-output/edi: (addr list var) = fn-outputs
23505     8b/-> *(ebp+0x10) 7/r32/edi
23506     # var curr-inout/esi: (addr stmt-var) = return-inouts
23507     8b/-> *(ebp+0xc) 6/r32/esi
23508     {
23509       # if (curr-output == 0) abort
23510       81 7/subop/compare %edi 0/imm32
23511       0f 84/jump-if-= break/disp32
23512       # if (curr-output->value->register != reg) continue
23513       (lookup *edi *(edi+4))  # List-value List-value => eax
23514       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
23515       (string-equal? %eax *(ebp+8))  # => eax
23516       3d/compare-eax-and 0/imm32/false
23517       0f 84/jump-if= $register-conflict?:continue/disp32
23518 #?       (write-buffered Stderr "rescan\n")
23519 #?       (flush Stderr)
23520       # var curr-reg/eax: (addr array byte) = curr-inout->value->register
23521       (lookup *esi *(esi+4))  # List-value List-value => eax
23522       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
23523       # if (curr-reg == 0) return true
23524       3d/compare-eax-and 0/imm32
23525       {
23526         75/jump-if-!= break/disp8
23527 #?         (write-buffered Stderr "no register\n")
23528 #?         (flush Stderr)
23529         b8/copy-to-eax 1/imm32/true
23530         e9/jump $register-conflict?:end/disp32
23531       }
23532       # return (curr-reg != reg)
23533       (string-equal? %eax *(ebp+8))  # => eax
23534       3d/compare-eax-and 0/imm32/false
23535       0f 94/set-if-= %al
23536 #?       (write-buffered Stderr "final: ")
23537 #?       (write-int32-hex-buffered Stderr %eax)
23538 #?       (write-buffered Stderr Newline)
23539 #?       (flush Stderr)
23540       eb/jump $register-conflict?:end/disp8
23541 $register-conflict?:continue:
23542       # curr-output = curr-output->next
23543       (lookup *(edi+8) *(edi+0xc))  # List-next List-next => eax
23544       89/<- %edi 0/r32/eax
23545       # curr-inout = curr-inout->next
23546       (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
23547       89/<- %esi 0/r32/eax
23548       e9/jump loop/disp32
23549     }
23550     # should never get here
23551     (write-buffered Stderr "register-conflict? misused\n")
23552     (flush Stderr)
23553     e8/call syscall_exit/disp32
23554 $register-conflict?:end:
23555     # . restore registers
23556     5f/pop-to-edi
23557     5e/pop-to-esi
23558     5b/pop-to-ebx
23559     5a/pop-to-edx
23560     59/pop-to-ecx
23561     # . epilogue
23562     89/<- %esp 5/r32/ebp
23563     5d/pop-to-ebp
23564     c3/return
23565 
23566 check-final-stmt-is-return:  # block: (addr block), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
23567     # . prologue
23568     55/push-ebp
23569     89/<- %ebp 4/r32/esp
23570     # . save registers
23571     50/push-eax
23572     51/push-ecx
23573     # var curr/ecx: (addr list stmt) = block->stmts
23574     8b/-> *(ebp+8) 0/r32/eax
23575     (lookup *(eax+4) *(eax+8))  # Block-stmts Block-stmts => eax
23576     3d/compare-eax-and 0/imm32
23577     74/jump-if-= $check-final-stmt-is-return:error/disp8
23578     89/<- %ecx 0/r32/eax
23579     {
23580       # if curr->next == 0, break
23581       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
23582       3d/compare-eax-and 0/imm32
23583       74/jump-if-= break/disp8
23584       # curr = curr->next
23585       89/<- %ecx 0/r32/eax
23586       e9/jump loop/disp32
23587     }
23588 $check-final-stmt-is-return:check-tag:
23589     # if curr->value->tag != Stmt1, abort
23590     (lookup *ecx *(ecx+4))  # List-value List-value => eax
23591     81 7/subop/compare *eax 1/imm32/stmt1  # Stmt-tag
23592     75/jump-if-!= $check-final-stmt-is-return:error/disp8
23593 $check-final-stmt-is-return:check-operation:
23594     # if curr->operation != "return", abort
23595     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
23596     (string-equal? %eax "return")
23597     3d/compare-eax-and 0/imm32/false
23598     74/jump-if-= $check-final-stmt-is-return:error/disp8
23599 $check-final-stmt-is-return:end:
23600     # . restore registers
23601     59/pop-to-ecx
23602     58/pop-to-eax
23603     # . epilogue
23604     89/<- %esp 5/r32/ebp
23605     5d/pop-to-ebp
23606     c3/return
23607 
23608 $check-final-stmt-is-return:error:
23609     (write-buffered *(ebp+0x10) "fn ")
23610     8b/-> *(ebp+0xc) 0/r32/eax
23611     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23612     (write-buffered *(ebp+0x10) %eax)
23613     (write-buffered *(ebp+0x10) ": final statement should be a 'return'\n")
23614     (flush *(ebp+0x10))
23615     (stop *(ebp+0x14) 1)
23616     # never gets here
23617 
23618 check-no-breaks:  # block: (addr block), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
23619     # . prologue
23620     55/push-ebp
23621     89/<- %ebp 4/r32/esp
23622     # . save registers
23623     50/push-eax
23624     51/push-ecx
23625     # var curr/ecx: (addr list stmt) = block->stmts
23626     8b/-> *(ebp+8) 0/r32/eax
23627     (lookup *(eax+4) *(eax+8))  # Block-stmts Block-stmts => eax
23628     3d/compare-eax-and 0/imm32
23629     0f 84/jump-if-= $check-no-breaks:end/disp32
23630     89/<- %ecx 0/r32/eax
23631     {
23632       # if curr->next == 0, break
23633       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
23634       3d/compare-eax-and 0/imm32
23635       74/jump-if-= break/disp8
23636       # if curr->value->tag != Stmt1, continue
23637       (lookup *ecx *(ecx+4))  # List-value List-value => eax
23638       81 7/subop/compare *eax 1/imm32/stmt1  # Stmt-tag
23639       75/jump-if-!= $check-no-breaks:continue/disp8
23640       # if curr->value->operation starts with "break", abort
23641       (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
23642       (string-starts-with? %eax "break")  # => eax
23643       3d/compare-eax-and 0/imm32/false
23644       75/jump-if-!= $check-no-breaks:error/disp8
23645 $check-no-breaks:continue:
23646       # curr = curr->next
23647       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
23648       89/<- %ecx 0/r32/eax
23649       e9/jump loop/disp32
23650     }
23651 $check-no-breaks:end:
23652     # . restore registers
23653     59/pop-to-ecx
23654     58/pop-to-eax
23655     # . epilogue
23656     89/<- %esp 5/r32/ebp
23657     5d/pop-to-ebp
23658     c3/return
23659 
23660 $check-no-breaks:error:
23661     (write-buffered *(ebp+0x10) "fn ")
23662     8b/-> *(ebp+0xc) 0/r32/eax
23663     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23664     (write-buffered *(ebp+0x10) %eax)
23665     (write-buffered *(ebp+0x10) " has outputs, so you cannot 'break' out of the outermost block. Use 'return'.\n")
23666     (flush *(ebp+0x10))
23667     (stop *(ebp+0x14) 1)
23668     # never gets here
23669 
23670 check-mu-get-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
23671     # . prologue
23672     55/push-ebp
23673     89/<- %ebp 4/r32/esp
23674     # . save registers
23675     50/push-eax
23676     51/push-ecx
23677     52/push-edx
23678     53/push-ebx
23679     56/push-esi
23680     57/push-edi
23681     # esi = stmt
23682     8b/-> *(ebp+8) 6/r32/esi
23683     # - check for 0 inouts
23684     # var base/ecx: (addr var) = stmt->inouts->value
23685     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23686     3d/compare-eax-and 0/imm32/false
23687     0f 84/jump-if-= $check-mu-get-stmt:error-too-few-inouts/disp32
23688     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
23689     89/<- %ecx 0/r32/eax
23690 $check-mu-get-stmt:check-base:
23691     # - check base type
23692     # if it's an 'addr', check that it's in a register
23693     # var base-type/ebx: (addr type-tree) = lookup(base->type)
23694     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
23695     89/<- %ebx 0/r32/eax
23696     {
23697       81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
23698       0f 85/jump-if-!= break/disp32
23699 $check-mu-get-stmt:base-is-compound:
23700       # if (type->left != addr) break
23701       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
23702       (simple-mu-type? %eax 2)  # addr => eax
23703       3d/compare-eax-and 0/imm32/false
23704       74/jump-if-= break/disp8
23705 $check-mu-get-stmt:base-is-addr:
23706       # now check for register
23707       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
23708       0f 84/jump-if-= $check-mu-get-stmt:error-base-type-addr-but-not-register/disp32
23709 $check-mu-get-stmt:base-is-addr-in-register:
23710       # type->left is now an addr; skip it
23711       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
23712       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
23713       0f 85/jump-if-!= $check-mu-get-stmt:error-bad-base/disp32
23714 $check-mu-get-stmt:base-is-addr-to-atom-in-register:
23715       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23716       89/<- %ebx 0/r32/eax
23717     }
23718 $check-mu-get-stmt:check-base-typeinfo:
23719     # ensure type is a container
23720     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
23721     {
23722       75/jump-if-!= break/disp8
23723       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
23724       89/<- %ebx 0/r32/eax
23725     }
23726     # var base-type-id/ebx: type-id = base-type->value
23727     8b/-> *(ebx+4) 3/r32/ebx  # Type-tree-value
23728     (container? %ebx)  # => eax
23729     3d/compare-eax-and 0/imm32/false
23730     0f 84/jump-if-= $check-mu-get-stmt:error-bad-base/disp32
23731     # var base-typeinfo/edx: (addr typeinfo) = find-typeinfo(base-type-id)
23732     # . var container/ecx: (handle typeinfo)
23733     68/push 0/imm32
23734     68/push 0/imm32
23735     89/<- %ecx 4/r32/esp
23736     # .
23737     (find-typeinfo %ebx %ecx)
23738     (lookup *ecx *(ecx+4))  # => eax
23739     # . reclaim container
23740     81 0/subop/add %esp 8/imm32
23741     # .
23742     89/<- %edx 0/r32/eax
23743     # var offset/ecx: (addr stmt-var) = stmt->inouts->next
23744     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23745     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
23746     89/<- %ecx 0/r32/eax
23747     # - check for 1 inout
23748     3d/compare-eax-and 0/imm32/false
23749     0f 84/jump-if-= $check-mu-get-stmt:error-too-few-inouts/disp32
23750     # var offset/ecx: (addr var) = lookup(offset->value)
23751     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
23752     89/<- %ecx 0/r32/eax
23753     # - check for valid field
23754     81 7/subop/compare *(ecx+0x14) -1/imm32/uninitialized  # Var-offset
23755     0f 84/jump-if-= $check-mu-get-stmt:error-bad-field/disp32
23756     # - check for too many inouts
23757     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23758     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
23759     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
23760     3d/compare-eax-and 0/imm32/false
23761     0f 85/jump-if-!= $check-mu-get-stmt:error-too-many-inouts/disp32
23762     # var output/edi: (addr var) = stmt->outputs->value
23763     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
23764     # - check for 0 outputs
23765     3d/compare-eax-and 0/imm32/false
23766     0f 84/jump-if-= $check-mu-get-stmt:error-too-few-outputs/disp32
23767     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
23768     89/<- %edi 0/r32/eax
23769 $check-mu-get-stmt:check-output-type:
23770     # - check output type
23771     # must be in register
23772     (lookup *(edi+0x18) *(edi+0x1c))  # Var-register Var-register => eax
23773     3d/compare-eax-and 0/imm32
23774     0f 84/jump-if-= $check-mu-get-stmt:error-output-not-in-register/disp32
23775     # must have a non-atomic type
23776     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
23777     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
23778     0f 85/jump-if-!= $check-mu-get-stmt:error-output-type-not-address/disp32
23779     # type must start with (addr ...)
23780     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23781     (simple-mu-type? %eax 2)  # => eax
23782     3d/compare-eax-and 0/imm32/false
23783     0f 84/jump-if-= $check-mu-get-stmt:error-output-type-not-address/disp32
23784 $check-mu-get-stmt:check-output-type-match:
23785     # payload of addr type must match 'type' definition
23786     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
23787     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
23788     # if (payload->right == null) payload = payload->left
23789     81 7/subop/compare *(eax+0xc) 0/imm32/null  # Type-tree-right
23790     {
23791       75/jump-if-!= break/disp8
23792       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23793     }
23794     89/<- %edi 0/r32/eax
23795     # . var output-name/ecx: (addr array byte)
23796     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
23797     89/<- %ecx 0/r32/eax
23798     # . var base-typeinfo-entry/eax: (addr handle typeinfo-entry)
23799     (lookup *(edx+4) *(edx+8))  # Typeinfo-fields Typeinfo-fields => eax
23800     (get %eax %ecx 0x10)  # => eax
23801     # .
23802     (lookup *eax *(eax+4))  # => eax
23803     (lookup *eax *(eax+4))  # Typeinfo-entry-input-var Typeinfo-entry-input-var => eax
23804     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
23805     # .
23806     (type-equal? %edi %eax)  # => eax
23807     3d/compare-eax-and 0/imm32/false
23808     0f 84/jump-if-= $check-mu-get-stmt:error-bad-output-type/disp32
23809     # - check for too many outputs
23810     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
23811     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
23812     3d/compare-eax-and 0/imm32/false
23813     0f 85/jump-if-!= $check-mu-get-stmt:error-too-many-outputs/disp32
23814 $check-mu-get-stmt:end:
23815     # . restore registers
23816     5f/pop-to-edi
23817     5e/pop-to-esi
23818     5b/pop-to-ebx
23819     5a/pop-to-edx
23820     59/pop-to-ecx
23821     58/pop-to-eax
23822     # . epilogue
23823     89/<- %esp 5/r32/ebp
23824     5d/pop-to-ebp
23825     c3/return
23826 
23827 $check-mu-get-stmt:error-too-few-inouts:
23828     (write-buffered *(ebp+0x10) "fn ")
23829     8b/-> *(ebp+0xc) 0/r32/eax
23830     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23831     (write-buffered *(ebp+0x10) %eax)
23832     (write-buffered *(ebp+0x10) ": stmt get: too few inouts (2 required)\n")
23833     (flush *(ebp+0x10))
23834     (stop *(ebp+0x14) 1)
23835     # never gets here
23836 
23837 $check-mu-get-stmt:error-too-many-inouts:
23838     (write-buffered *(ebp+0x10) "fn ")
23839     8b/-> *(ebp+0xc) 0/r32/eax
23840     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23841     (write-buffered *(ebp+0x10) %eax)
23842     (write-buffered *(ebp+0x10) ": stmt get: too many inouts (2 required)\n")
23843     (flush *(ebp+0x10))
23844     (stop *(ebp+0x14) 1)
23845     # never gets here
23846 
23847 $check-mu-get-stmt:error-too-few-outputs:
23848     (write-buffered *(ebp+0x10) "fn ")
23849     8b/-> *(ebp+0xc) 0/r32/eax
23850     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23851     (write-buffered *(ebp+0x10) %eax)
23852     (write-buffered *(ebp+0x10) ": stmt get: must have an output\n")
23853     (flush *(ebp+0x10))
23854     (stop *(ebp+0x14) 1)
23855     # never gets here
23856 
23857 $check-mu-get-stmt:error-too-many-outputs:
23858     (write-buffered *(ebp+0x10) "fn ")
23859     8b/-> *(ebp+0xc) 0/r32/eax
23860     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23861     (write-buffered *(ebp+0x10) %eax)
23862     (write-buffered *(ebp+0x10) ": stmt get: too many outputs (1 required)\n")
23863     (flush *(ebp+0x10))
23864     (stop *(ebp+0x14) 1)
23865     # never gets here
23866 
23867 $check-mu-get-stmt:error-bad-base:
23868     # error("fn " fn ": stmt get: var '" base->name "' must have a 'type' definition\n")
23869     (write-buffered *(ebp+0x10) "fn ")
23870     8b/-> *(ebp+0xc) 0/r32/eax
23871     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23872     (write-buffered *(ebp+0x10) %eax)
23873     (write-buffered *(ebp+0x10) ": stmt get: var '")
23874     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23875     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
23876     (lookup *eax *(eax+4))  # Var-name Var-name => eax
23877     (write-buffered *(ebp+0x10) %eax)
23878     (write-buffered *(ebp+0x10) "' must have a 'type' definition\n")
23879     (flush *(ebp+0x10))
23880     (stop *(ebp+0x14) 1)
23881     # never gets here
23882 
23883 $check-mu-get-stmt:error-base-type-addr-but-not-register:
23884     (write-buffered *(ebp+0x10) "fn ")
23885     8b/-> *(ebp+0xc) 0/r32/eax
23886     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23887     (write-buffered *(ebp+0x10) %eax)
23888     (write-buffered *(ebp+0x10) ": stmt get: var '")
23889     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23890     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
23891     (lookup *eax *(eax+4))  # Var-name Var-name => eax
23892     (write-buffered *(ebp+0x10) %eax)
23893     (write-buffered *(ebp+0x10) "' is an 'addr' type, and so must live in a register\n")
23894     (flush *(ebp+0x10))
23895     (stop *(ebp+0x14) 1)
23896     # never gets here
23897 
23898 $check-mu-get-stmt:error-bad-field:
23899     # error("fn " fn ": stmt get: type " type " has no member called '" curr->name "'\n")
23900     (write-buffered *(ebp+0x10) "fn ")
23901     8b/-> *(ebp+0xc) 0/r32/eax
23902     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23903     (write-buffered *(ebp+0x10) %eax)
23904     (write-buffered *(ebp+0x10) ": stmt get: type '")
23905     # . write(Type-id->data[tmp])
23906     bf/copy-to-edi Type-id/imm32
23907     8b/-> *(edi+ebx<<2+0xc) 6/r32/esi
23908     {
23909       81 7/subop/compare %esi 0/imm32
23910       74/jump-if-= break/disp8
23911       (write-buffered *(ebp+0x10) %esi)
23912     }
23913     # .
23914     (write-buffered *(ebp+0x10) "' has no member called '")
23915     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
23916     (write-buffered *(ebp+0x10) %eax)
23917     (write-buffered *(ebp+0x10) "'\n")
23918     (flush *(ebp+0x10))
23919     (stop *(ebp+0x14) 1)
23920     # never gets here
23921 
23922 $check-mu-get-stmt:error-output-not-in-register:
23923     (write-buffered *(ebp+0x10) "fn ")
23924     8b/-> *(ebp+0xc) 0/r32/eax
23925     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23926     (write-buffered *(ebp+0x10) %eax)
23927     (write-buffered *(ebp+0x10) ": stmt get: output '")
23928     (lookup *edi *(edi+4))  # Var-name Var-name => eax
23929     (write-buffered *(ebp+0x10) %eax)
23930     (write-buffered *(ebp+0x10) "' is not in a register\n")
23931     (flush *(ebp+0x10))
23932     (stop *(ebp+0x14) 1)
23933     # never gets here
23934 
23935 $check-mu-get-stmt:error-output-type-not-address:
23936     (write-buffered *(ebp+0x10) "fn ")
23937     8b/-> *(ebp+0xc) 0/r32/eax
23938     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23939     (write-buffered *(ebp+0x10) %eax)
23940     (write-buffered *(ebp+0x10) ": stmt get: output must be an addr\n")
23941     (flush *(ebp+0x10))
23942     (stop *(ebp+0x14) 1)
23943     # never gets here
23944 
23945 $check-mu-get-stmt:error-bad-output-type:
23946     (write-buffered *(ebp+0x10) "fn ")
23947     8b/-> *(ebp+0xc) 0/r32/eax
23948     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23949     (write-buffered *(ebp+0x10) %eax)
23950     (write-buffered *(ebp+0x10) ": stmt get: wrong output type for member '")
23951     (write-buffered *(ebp+0x10) %ecx)
23952     (write-buffered *(ebp+0x10) "' of type '")
23953     bf/copy-to-edi Type-id/imm32
23954     8b/-> *(edi+ebx<<2+0xc) 6/r32/esi
23955     {
23956       81 7/subop/compare %esi 0/imm32
23957       74/jump-if-= break/disp8
23958       (write-buffered *(ebp+0x10) %esi)
23959     }
23960     (write-buffered *(ebp+0x10) "'\n")
23961     (flush *(ebp+0x10))
23962     (stop *(ebp+0x14) 1)
23963     # never gets here
23964 
23965 check-mu-index-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
23966     # . prologue
23967     55/push-ebp
23968     89/<- %ebp 4/r32/esp
23969     # . save registers
23970     50/push-eax
23971     51/push-ecx
23972     52/push-edx
23973     53/push-ebx
23974     56/push-esi
23975     57/push-edi
23976     # esi = stmt
23977     8b/-> *(ebp+8) 6/r32/esi
23978     # - check for 0 inouts
23979     # var base/ecx: (addr var) = stmt->inouts->value
23980     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23981 $check-mu-index-stmt:check-no-inouts:
23982     3d/compare-eax-and 0/imm32
23983     0f 84/jump-if-= $check-mu-index-stmt:error-too-few-inouts/disp32
23984     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
23985     89/<- %ecx 0/r32/eax
23986     # - check base type is either (addr array ...) in register or (array ...) on stack
23987     # var base-type/ebx: (addr type-tree) = lookup(base->type)
23988     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
23989     89/<- %ebx 0/r32/eax
23990     # if base-type is an atom, abort with a precise error
23991     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
23992     {
23993       74/jump-if-= break/disp8
23994       (simple-mu-type? %ebx 3)  # array => eax
23995       3d/compare-eax-and 0/imm32/false
23996       0f 85/jump-if-!= $check-mu-index-stmt:error-base-array-atom-type/disp32
23997       0f 84/jump-if-= $check-mu-index-stmt:error-base-non-array-type/disp32
23998     }
23999 $check-mu-index-stmt:base-is-compound:
24000     # if type->left not addr or array, abort
24001     {
24002       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24003       (simple-mu-type? %eax 2)  # addr => eax
24004       3d/compare-eax-and 0/imm32/false
24005       75/jump-if-!= break/disp8
24006       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24007       (simple-mu-type? %eax 3)  # array => eax
24008       3d/compare-eax-and 0/imm32/false
24009       75/jump-if-!= break/disp8
24010       e9/jump $check-mu-index-stmt:error-base-non-array-type/disp32
24011     }
24012     # if (type->left == addr) ensure type->right->left == array and type->register exists
24013     {
24014       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24015       (simple-mu-type? %eax 2)  # addr => eax
24016       3d/compare-eax-and 0/imm32/false
24017       74/jump-if-= break/disp8
24018 $check-mu-index-stmt:base-is-addr:
24019       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
24020       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
24021       (simple-mu-type? %eax 3)  # array => eax
24022       3d/compare-eax-and 0/imm32/false
24023       0f 84/jump-if-= $check-mu-index-stmt:error-base-non-array-type/disp32
24024 $check-mu-index-stmt:check-base-addr-is-register:
24025       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
24026       0f 84/jump-if-= $check-mu-index-stmt:error-base-address-array-type-on-stack/disp32
24027     }
24028     # if (type->left == array) ensure type->register doesn't exist
24029     {
24030       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24031       (simple-mu-type? %eax 3)  # array => eax
24032       3d/compare-eax-and 0/imm32/false
24033       74/jump-if-= break/disp8
24034 $check-mu-index-stmt:base-is-array:
24035       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
24036       0f 85/jump-if-!= $check-mu-index-stmt:error-base-array-type-in-register/disp32
24037     }
24038     # if (base-type->left == addr) base-type = base-type->right
24039     {
24040       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24041       (simple-mu-type? %eax 2)  # addr => eax
24042       3d/compare-eax-and 0/imm32/false
24043       74/jump-if-= break/disp8
24044       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
24045       89/<- %ebx 0/r32/eax
24046     }
24047     # - check for 1 inout
24048     # var index/ecx: (addr stmt-var) = stmt->inouts->next->value
24049     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
24050     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
24051 $check-mu-index-stmt:check-single-inout:
24052     3d/compare-eax-and 0/imm32
24053     0f 84/jump-if-= $check-mu-index-stmt:error-too-few-inouts/disp32
24054     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
24055     89/<- %ecx 0/r32/eax
24056     # - check index is either a literal or register
24057     # var index-type/edx: (addr type-tree)
24058     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
24059     89/<- %edx 0/r32/eax
24060     # if index type is an atom, it must be a literal or int
24061     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
24062     {
24063       74/jump-if-= break/disp8
24064 $check-mu-index-stmt:index-type-is-atom:
24065       (simple-mu-type? %edx 0)  # literal => eax
24066       3d/compare-eax-and 0/imm32/false
24067       75/jump-if-!= $check-mu-index-stmt:index-type-done/disp8
24068       (simple-mu-type? %edx 1)  # int => eax
24069       3d/compare-eax-and 0/imm32/false
24070       75/jump-if-!= $check-mu-index-stmt:index-type-done/disp8
24071       (simple-mu-type? %edx 7)  # offset => eax
24072       3d/compare-eax-and 0/imm32/false
24073       0f 85/jump-if-!= $check-mu-index-stmt:error-index-offset-atom-type/disp32
24074       e9/jump $check-mu-index-stmt:error-invalid-index-type/disp32
24075     }
24076     # if index type is a non-atom: it must be an offset
24077     {
24078       75/jump-if-!= break/disp8
24079 $check-mu-index-stmt:index-type-is-non-atom:
24080       (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
24081       (simple-mu-type? %eax 7)  # offset => eax
24082       3d/compare-eax-and 0/imm32/false
24083       0f 84/jump-if-= $check-mu-index-stmt:error-invalid-index-type/disp32
24084     }
24085 $check-mu-index-stmt:index-type-done:
24086     # check index is either a literal or in a register
24087     {
24088       (simple-mu-type? %edx 0)  # literal => eax
24089       3d/compare-eax-and 0/imm32/false
24090       75/jump-if-!= break/disp8
24091 $check-mu-index-stmt:check-index-in-register:
24092       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
24093       0f 84/jump-if-= $check-mu-index-stmt:error-index-on-stack/disp32
24094     }
24095     # - if index is an 'int', check that element type of base has size 1, 2, 4 or 8 bytes.
24096     {
24097       (simple-mu-type? %edx 1)  # int => eax
24098       3d/compare-eax-and 0/imm32/false
24099       74/jump-if-= break/disp8
24100 $check-mu-index-stmt:check-index-can-be-int:
24101       (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
24102       (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
24103       (array-element-size %eax)  # => eax
24104       3d/compare-eax-and 1/imm32
24105       74/jump-if-= break/disp8
24106       3d/compare-eax-and 2/imm32
24107       74/jump-if-= break/disp8
24108       3d/compare-eax-and 4/imm32
24109       74/jump-if-= break/disp8
24110       3d/compare-eax-and 8/imm32
24111       74/jump-if-= break/disp8
24112       e9/jump $check-mu-index-stmt:error-index-needs-offset/disp32
24113     }
24114     # - check for too many inouts
24115     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
24116     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
24117     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
24118     3d/compare-eax-and 0/imm32/false
24119     0f 85/jump-if-!= $check-mu-index-stmt:error-too-many-inouts/disp32
24120     # - check for 0 outputs
24121     # var output/edi: (addr var) = stmt->outputs->value
24122     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
24123     3d/compare-eax-and 0/imm32/false
24124     0f 84/jump-if-= $check-mu-index-stmt:error-too-few-outputs/disp32
24125     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
24126     89/<- %edi 0/r32/eax
24127     # - check output type
24128     # must have a non-atomic type
24129     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
24130     89/<- %edx 0/r32/eax
24131     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
24132     0f 85/jump-if-!= $check-mu-index-stmt:error-output-type-not-address/disp32
24133     # type must start with (addr ...)
24134     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
24135     (simple-mu-type? %eax 2)  # addr => eax
24136     3d/compare-eax-and 0/imm32/false
24137     0f 84/jump-if-= $check-mu-index-stmt:error-output-type-not-address/disp32
24138     # if tail(base-type) != tail(output-type) abort
24139     (type-tail %ebx)  # => eax
24140     89/<- %ebx 0/r32/eax
24141     (type-tail %edx)  # => eax
24142     (type-equal? %ebx %eax)  # => eax
24143     3d/compare-eax-and 0/imm32/false
24144     0f 84/jump-if-= $check-mu-index-stmt:error-bad-output-type/disp32
24145     # - check for too many outputs
24146     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
24147     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
24148     3d/compare-eax-and 0/imm32/false
24149     0f 85/jump-if-!= $check-mu-index-stmt:error-too-many-outputs/disp32
24150 $check-mu-index-stmt:end:
24151     # . restore registers
24152     5f/pop-to-edi
24153     5e/pop-to-esi
24154     5b/pop-to-ebx
24155     5a/pop-to-edx
24156     59/pop-to-ecx
24157     58/pop-to-eax
24158     # . epilogue
24159     89/<- %esp 5/r32/ebp
24160     5d/pop-to-ebp
24161     c3/return
24162 
24163 $check-mu-index-stmt:error-base-non-array-type:
24164     (write-buffered *(ebp+0x10) "fn ")
24165     8b/-> *(ebp+0xc) 0/r32/eax
24166     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24167     (write-buffered *(ebp+0x10) %eax)
24168     (write-buffered *(ebp+0x10) ": stmt index: var '")
24169     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24170     (write-buffered *(ebp+0x10) %eax)
24171     (write-buffered *(ebp+0x10) "' is not an array\n")
24172     (flush *(ebp+0x10))
24173     (stop *(ebp+0x14) 1)
24174     # never gets here
24175 
24176 $check-mu-index-stmt:error-base-array-atom-type:
24177     (write-buffered *(ebp+0x10) "fn ")
24178     8b/-> *(ebp+0xc) 0/r32/eax
24179     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24180     (write-buffered *(ebp+0x10) %eax)
24181     (write-buffered *(ebp+0x10) ": stmt index: array '")
24182     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24183     (write-buffered *(ebp+0x10) %eax)
24184     (write-buffered *(ebp+0x10) "' must specify the type of its elements\n")
24185     (flush *(ebp+0x10))
24186     (stop *(ebp+0x14) 1)
24187     # never gets here
24188 
24189 $check-mu-index-stmt:error-base-address-array-type-on-stack:
24190     (write-buffered *(ebp+0x10) "fn ")
24191     8b/-> *(ebp+0xc) 0/r32/eax
24192     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24193     (write-buffered *(ebp+0x10) %eax)
24194     (write-buffered *(ebp+0x10) ": stmt index: var '")
24195     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24196     (write-buffered *(ebp+0x10) %eax)
24197     (write-buffered *(ebp+0x10) "' is an addr to an array, and so must live in a register\n")
24198     (flush *(ebp+0x10))
24199     (stop *(ebp+0x14) 1)
24200     # never gets here
24201 
24202 $check-mu-index-stmt:error-base-array-type-in-register:
24203     (write-buffered *(ebp+0x10) "fn ")
24204     8b/-> *(ebp+0xc) 0/r32/eax
24205     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24206     (write-buffered *(ebp+0x10) %eax)
24207     (write-buffered *(ebp+0x10) ": stmt index: var '")
24208     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24209     (write-buffered *(ebp+0x10) %eax)
24210     (write-buffered *(ebp+0x10) "' is an array, and so must live on the stack\n")
24211     (flush *(ebp+0x10))
24212     (stop *(ebp+0x14) 1)
24213     # never gets here
24214 
24215 $check-mu-index-stmt:error-too-few-inouts:
24216     (write-buffered *(ebp+0x10) "fn ")
24217     8b/-> *(ebp+0xc) 0/r32/eax
24218     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24219     (write-buffered *(ebp+0x10) %eax)
24220     (write-buffered *(ebp+0x10) ": stmt index: too few inouts (2 required)\n")
24221     (flush *(ebp+0x10))
24222     (stop *(ebp+0x14) 1)
24223     # never gets here
24224 
24225 $check-mu-index-stmt:error-invalid-index-type:
24226     (write-buffered *(ebp+0x10) "fn ")
24227     8b/-> *(ebp+0xc) 0/r32/eax
24228     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24229     (write-buffered *(ebp+0x10) %eax)
24230     (write-buffered *(ebp+0x10) ": stmt index: second argument '")
24231     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24232     (write-buffered *(ebp+0x10) %eax)
24233     (write-buffered *(ebp+0x10) "' must be an int or offset\n")
24234     (flush *(ebp+0x10))
24235     (stop *(ebp+0x14) 1)
24236     # never gets here
24237 
24238 $check-mu-index-stmt:error-index-offset-atom-type:
24239     (write-buffered *(ebp+0x10) "fn ")
24240     8b/-> *(ebp+0xc) 0/r32/eax
24241     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24242     (write-buffered *(ebp+0x10) %eax)
24243     (write-buffered *(ebp+0x10) ": stmt index: offset '")
24244     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24245     (write-buffered *(ebp+0x10) %eax)
24246     (write-buffered *(ebp+0x10) "' must specify the type of array elements\n")
24247     (flush *(ebp+0x10))
24248     (stop *(ebp+0x14) 1)
24249     # never gets here
24250 
24251 $check-mu-index-stmt:error-index-on-stack:
24252     (write-buffered *(ebp+0x10) "fn ")
24253     8b/-> *(ebp+0xc) 0/r32/eax
24254     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24255     (write-buffered *(ebp+0x10) %eax)
24256     (write-buffered *(ebp+0x10) ": stmt index: second argument '")
24257     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24258     (write-buffered *(ebp+0x10) %eax)
24259     (write-buffered *(ebp+0x10) "' must be in a register\n")
24260     (flush *(ebp+0x10))
24261     (stop *(ebp+0x14) 1)
24262     # never gets here
24263 
24264 $check-mu-index-stmt:error-index-needs-offset:
24265     (write-buffered *(ebp+0x10) "fn ")
24266     8b/-> *(ebp+0xc) 0/r32/eax
24267     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24268     (write-buffered *(ebp+0x10) %eax)
24269     (write-buffered *(ebp+0x10) ": stmt index: cannot take an int for array '")
24270     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
24271     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
24272     (lookup *eax *(eax+4))  # Var-name Var-name => eax
24273     (write-buffered *(ebp+0x10) %eax)
24274     (write-buffered *(ebp+0x10) "'; create an offset instead. See mu.md for details.\n")
24275     (flush *(ebp+0x10))
24276     (stop *(ebp+0x14) 1)
24277     # never gets here
24278 
24279 $check-mu-index-stmt:error-too-many-inouts:
24280     (write-buffered *(ebp+0x10) "fn ")
24281     8b/-> *(ebp+0xc) 0/r32/eax
24282     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24283     (write-buffered *(ebp+0x10) %eax)
24284     (write-buffered *(ebp+0x10) ": stmt index: too many inouts (2 required)\n")
24285     (flush *(ebp+0x10))
24286     (stop *(ebp+0x14) 1)
24287     # never gets here
24288 
24289 $check-mu-index-stmt:error-too-few-outputs:
24290     (write-buffered *(ebp+0x10) "fn ")
24291     8b/-> *(ebp+0xc) 0/r32/eax
24292     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24293     (write-buffered *(ebp+0x10) %eax)
24294     (write-buffered *(ebp+0x10) ": stmt index: must have an output\n")
24295     (flush *(ebp+0x10))
24296     (stop *(ebp+0x14) 1)
24297     # never gets here
24298 
24299 $check-mu-index-stmt:error-too-many-outputs:
24300     (write-buffered *(ebp+0x10) "fn ")
24301     8b/-> *(ebp+0xc) 0/r32/eax
24302     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24303     (write-buffered *(ebp+0x10) %eax)
24304     (write-buffered *(ebp+0x10) ": stmt index: too many outputs (1 required)\n")
24305     (flush *(ebp+0x10))
24306     (stop *(ebp+0x14) 1)
24307     # never gets here
24308 
24309 $check-mu-index-stmt:error-output-not-in-register:
24310     (write-buffered *(ebp+0x10) "fn ")
24311     8b/-> *(ebp+0xc) 0/r32/eax
24312     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24313     (write-buffered *(ebp+0x10) %eax)
24314     (write-buffered *(ebp+0x10) ": stmt index: output '")
24315     (lookup *edi *(edi+4))  # Var-name Var-name => eax
24316     (write-buffered *(ebp+0x10) %eax)
24317     (write-buffered *(ebp+0x10) "' is not in a register\n")
24318     (flush *(ebp+0x10))
24319     (stop *(ebp+0x14) 1)
24320     # never gets here
24321 
24322 $check-mu-index-stmt:error-output-type-not-address:
24323     (write-buffered *(ebp+0x10) "fn ")
24324     8b/-> *(ebp+0xc) 0/r32/eax
24325     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24326     (write-buffered *(ebp+0x10) %eax)
24327     (write-buffered *(ebp+0x10) ": stmt index: output '")
24328     (lookup *edi *(edi+4))  # Var-name Var-name => eax
24329     (write-buffered *(ebp+0x10) %eax)
24330     (write-buffered *(ebp+0x10) "' must be an addr\n")
24331     (flush *(ebp+0x10))
24332     (stop *(ebp+0x14) 1)
24333     # never gets here
24334 
24335 $check-mu-index-stmt:error-bad-output-type:
24336     (write-buffered *(ebp+0x10) "fn ")
24337     8b/-> *(ebp+0xc) 0/r32/eax
24338     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24339     (write-buffered *(ebp+0x10) %eax)
24340     (write-buffered *(ebp+0x10) ": stmt index: output '")
24341     (lookup *edi *(edi+4))  # Var-name Var-name => eax
24342     (write-buffered *(ebp+0x10) %eax)
24343     (write-buffered *(ebp+0x10) "' does not have the right type\n")
24344     (flush *(ebp+0x10))
24345     (stop *(ebp+0x14) 1)
24346     # never gets here
24347 
24348 check-mu-length-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
24349     # . prologue
24350     55/push-ebp
24351     89/<- %ebp 4/r32/esp
24352     # . save registers
24353     50/push-eax
24354     51/push-ecx
24355     52/push-edx
24356     53/push-ebx
24357     56/push-esi
24358     57/push-edi
24359     # esi = stmt
24360     8b/-> *(ebp+8) 6/r32/esi
24361     # - check for 0 inouts
24362     # var base/ecx: (addr var) = stmt->inouts->value
24363     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
24364 $check-mu-length-stmt:check-no-inouts:
24365     3d/compare-eax-and 0/imm32
24366     0f 84/jump-if-= $check-mu-length-stmt:error-too-few-inouts/disp32
24367     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
24368     89/<- %ecx 0/r32/eax
24369     # - check base type is either (addr array ...) in register or (array ...) on stack
24370     # var base-type/ebx: (addr type-tree) = lookup(base->type)
24371     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
24372     89/<- %ebx 0/r32/eax
24373     # if base-type is an atom, abort with a precise error
24374     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
24375     {
24376       74/jump-if-= break/disp8
24377       (simple-mu-type? %ebx 3)  # array => eax
24378       3d/compare-eax-and 0/imm32/false
24379       0f 85/jump-if-!= $check-mu-length-stmt:error-base-array-atom-type/disp32
24380       0f 84/jump-if-= $check-mu-length-stmt:error-base-non-array-type/disp32
24381     }
24382 $check-mu-length-stmt:base-is-compound:
24383     # if type->left not addr or array, abort
24384     {
24385       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24386       (simple-mu-type? %eax 2)  # addr => eax
24387       3d/compare-eax-and 0/imm32/false
24388       75/jump-if-!= break/disp8
24389       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24390       (simple-mu-type? %eax 3)  # array => eax
24391       3d/compare-eax-and 0/imm32/false
24392       75/jump-if-!= break/disp8
24393       e9/jump $check-mu-length-stmt:error-base-non-array-type/disp32
24394     }
24395     # if (type->left == addr) ensure type->right->left == array and type->register exists
24396     {
24397       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24398       (simple-mu-type? %eax 2)  # addr => eax
24399       3d/compare-eax-and 0/imm32/false
24400       74/jump-if-= break/disp8
24401 $check-mu-length-stmt:base-is-addr:
24402       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
24403       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
24404       (simple-mu-type? %eax 3)  # array => eax
24405       3d/compare-eax-and 0/imm32/false
24406       0f 84/jump-if-= $check-mu-length-stmt:error-base-non-array-type/disp32
24407 $check-mu-length-stmt:check-base-addr-is-register:
24408       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
24409       0f 84/jump-if-= $check-mu-length-stmt:error-base-address-array-type-on-stack/disp32
24410     }
24411     # if (type->left == array) ensure type->register doesn't exist
24412     {
24413       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24414       (simple-mu-type? %eax 3)  # array => eax
24415       3d/compare-eax-and 0/imm32/false
24416       74/jump-if-= break/disp8
24417 $check-mu-length-stmt:base-is-array:
24418       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
24419       0f 85/jump-if-!= $check-mu-length-stmt:error-base-array-type-in-register/disp32
24420     }
24421     # if (base-type->left == addr) base-type = base-type->right
24422     {
24423       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24424       (simple-mu-type? %eax 2)  # addr => eax
24425       3d/compare-eax-and 0/imm32/false
24426       74/jump-if-= break/disp8
24427       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
24428       89/<- %ebx 0/r32/eax
24429     }
24430     # - check for too many inouts
24431     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
24432     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
24433     3d/compare-eax-and 0/imm32/false
24434     0f 85/jump-if-!= $check-mu-length-stmt:error-too-many-inouts/disp32
24435     # - check for 0 outputs
24436     # var output/edi: (addr var) = stmt->outputs->value
24437     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
24438     3d/compare-eax-and 0/imm32/false
24439     0f 84/jump-if-= $check-mu-length-stmt:error-too-few-outputs/disp32
24440     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
24441     89/<- %edi 0/r32/eax
24442     # - check output type
24443     # must have a non-atomic type
24444     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
24445     (simple-mu-type? %eax 1)  # int => eax
24446     3d/compare-eax-and 0/imm32/false
24447     0f 84/jump-if-= $check-mu-length-stmt:error-invalid-output-type/disp32
24448     # - check for too many outputs
24449     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
24450     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
24451     3d/compare-eax-and 0/imm32/false
24452     0f 85/jump-if-!= $check-mu-length-stmt:error-too-many-outputs/disp32
24453 $check-mu-length-stmt:end:
24454     # . restore registers
24455     5f/pop-to-edi
24456     5e/pop-to-esi
24457     5b/pop-to-ebx
24458     5a/pop-to-edx
24459     59/pop-to-ecx
24460     58/pop-to-eax
24461     # . epilogue
24462     89/<- %esp 5/r32/ebp
24463     5d/pop-to-ebp
24464     c3/return
24465 
24466 $check-mu-length-stmt:error-base-non-array-type:
24467     (write-buffered *(ebp+0x10) "fn ")
24468     8b/-> *(ebp+0xc) 0/r32/eax
24469     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24470     (write-buffered *(ebp+0x10) %eax)
24471     (write-buffered *(ebp+0x10) ": stmt length: var '")
24472     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24473     (write-buffered *(ebp+0x10) %eax)
24474     (write-buffered *(ebp+0x10) "' is not an array\n")
24475     (flush *(ebp+0x10))
24476     (stop *(ebp+0x14) 1)
24477     # never gets here
24478 
24479 $check-mu-length-stmt:error-base-array-atom-type:
24480     (write-buffered *(ebp+0x10) "fn ")
24481     8b/-> *(ebp+0xc) 0/r32/eax
24482     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24483     (write-buffered *(ebp+0x10) %eax)
24484     (write-buffered *(ebp+0x10) ": stmt length: array '")
24485     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24486     (write-buffered *(ebp+0x10) %eax)
24487     (write-buffered *(ebp+0x10) "' must specify the type of its elements\n")
24488     (flush *(ebp+0x10))
24489     (stop *(ebp+0x14) 1)
24490     # never gets here
24491 
24492 $check-mu-length-stmt:error-base-address-array-type-on-stack:
24493     (write-buffered *(ebp+0x10) "fn ")
24494     8b/-> *(ebp+0xc) 0/r32/eax
24495     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24496     (write-buffered *(ebp+0x10) %eax)
24497     (write-buffered *(ebp+0x10) ": stmt length: var '")
24498     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24499     (write-buffered *(ebp+0x10) %eax)
24500     (write-buffered *(ebp+0x10) "' is an addr to an array, and so must live in a register\n")
24501     (flush *(ebp+0x10))
24502     (stop *(ebp+0x14) 1)
24503     # never gets here
24504 
24505 $check-mu-length-stmt:error-base-array-type-in-register:
24506     (write-buffered *(ebp+0x10) "fn ")
24507     8b/-> *(ebp+0xc) 0/r32/eax
24508     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24509     (write-buffered *(ebp+0x10) %eax)
24510     (write-buffered *(ebp+0x10) ": stmt length: var '")
24511     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24512     (write-buffered *(ebp+0x10) %eax)
24513     (write-buffered *(ebp+0x10) "' is an array, and so must live on the stack\n")
24514     (flush *(ebp+0x10))
24515     (stop *(ebp+0x14) 1)
24516     # never gets here
24517 
24518 $check-mu-length-stmt:error-too-few-inouts:
24519     (write-buffered *(ebp+0x10) "fn ")
24520     8b/-> *(ebp+0xc) 0/r32/eax
24521     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24522     (write-buffered *(ebp+0x10) %eax)
24523     (write-buffered *(ebp+0x10) ": stmt length: too few inouts (1 required)\n")
24524     (flush *(ebp+0x10))
24525     (stop *(ebp+0x14) 1)
24526     # never gets here
24527 
24528 $check-mu-length-stmt:error-invalid-index-type:
24529     (write-buffered *(ebp+0x10) "fn ")
24530     8b/-> *(ebp+0xc) 0/r32/eax
24531     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24532     (write-buffered *(ebp+0x10) %eax)
24533     (write-buffered *(ebp+0x10) ": stmt length: second argument '")
24534     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24535     (write-buffered *(ebp+0x10) %eax)
24536     (write-buffered *(ebp+0x10) "' must be an int or offset\n")
24537     (flush *(ebp+0x10))
24538     (stop *(ebp+0x14) 1)
24539     # never gets here
24540 
24541 $check-mu-length-stmt:error-index-offset-atom-type:
24542     (write-buffered *(ebp+0x10) "fn ")
24543     8b/-> *(ebp+0xc) 0/r32/eax
24544     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24545     (write-buffered *(ebp+0x10) %eax)
24546     (write-buffered *(ebp+0x10) ": stmt length: offset '")
24547     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24548     (write-buffered *(ebp+0x10) %eax)
24549     (write-buffered *(ebp+0x10) "' must specify the type of array elements\n")
24550     (flush *(ebp+0x10))
24551     (stop *(ebp+0x14) 1)
24552     # never gets here
24553 
24554 $check-mu-length-stmt:error-index-on-stack:
24555     (write-buffered *(ebp+0x10) "fn ")
24556     8b/-> *(ebp+0xc) 0/r32/eax
24557     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24558     (write-buffered *(ebp+0x10) %eax)
24559     (write-buffered *(ebp+0x10) ": stmt length: second argument '")
24560     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24561     (write-buffered *(ebp+0x10) %eax)
24562     (write-buffered *(ebp+0x10) "' must be in a register\n")
24563     (flush *(ebp+0x10))
24564     (stop *(ebp+0x14) 1)
24565     # never gets here
24566 
24567 $check-mu-length-stmt:error-index-needs-offset:
24568     (write-buffered *(ebp+0x10) "fn ")
24569     8b/-> *(ebp+0xc) 0/r32/eax
24570     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24571     (write-buffered *(ebp+0x10) %eax)
24572     (write-buffered *(ebp+0x10) ": stmt length: cannot take an int for array '")
24573     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
24574     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
24575     (lookup *eax *(eax+4))  # Var-name Var-name => eax
24576     (write-buffered *(ebp+0x10) %eax)
24577     (write-buffered *(ebp+0x10) "'; create an offset instead. See mu.md for details.\n")
24578     (flush *(ebp+0x10))
24579     (stop *(ebp+0x14) 1)
24580     # never gets here
24581 
24582 $check-mu-length-stmt:error-too-many-inouts:
24583     (write-buffered *(ebp+0x10) "fn ")
24584     8b/-> *(ebp+0xc) 0/r32/eax
24585     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24586     (write-buffered *(ebp+0x10) %eax)
24587     (write-buffered *(ebp+0x10) ": stmt length: too many inouts (1 required)\n")
24588     (flush *(ebp+0x10))
24589     (stop *(ebp+0x14) 1)
24590     # never gets here
24591 
24592 $check-mu-length-stmt:error-too-few-outputs:
24593     (write-buffered *(ebp+0x10) "fn ")
24594     8b/-> *(ebp+0xc) 0/r32/eax
24595     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24596     (write-buffered *(ebp+0x10) %eax)
24597     (write-buffered *(ebp+0x10) ": stmt length: must have an output\n")
24598     (flush *(ebp+0x10))
24599     (stop *(ebp+0x14) 1)
24600     # never gets here
24601 
24602 $check-mu-length-stmt:error-too-many-outputs:
24603     (write-buffered *(ebp+0x10) "fn ")
24604     8b/-> *(ebp+0xc) 0/r32/eax
24605     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24606     (write-buffered *(ebp+0x10) %eax)
24607     (write-buffered *(ebp+0x10) ": stmt length: too many outputs (1 required)\n")
24608     (flush *(ebp+0x10))
24609     (stop *(ebp+0x14) 1)
24610     # never gets here
24611 
24612 $check-mu-length-stmt:error-output-not-in-register:
24613     (write-buffered *(ebp+0x10) "fn ")
24614     8b/-> *(ebp+0xc) 0/r32/eax
24615     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24616     (write-buffered *(ebp+0x10) %eax)
24617     (write-buffered *(ebp+0x10) ": stmt length: output '")
24618     (lookup *edi *(edi+4))  # Var-name Var-name => eax
24619     (write-buffered *(ebp+0x10) %eax)
24620     (write-buffered *(ebp+0x10) "' is not in a register\n")
24621     (flush *(ebp+0x10))
24622     (stop *(ebp+0x14) 1)
24623     # never gets here
24624 
24625 $check-mu-length-stmt:error-invalid-output-type:
24626     (write-buffered *(ebp+0x10) "fn ")
24627     8b/-> *(ebp+0xc) 0/r32/eax
24628     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24629     (write-buffered *(ebp+0x10) %eax)
24630     (write-buffered *(ebp+0x10) ": stmt length: output '")
24631     (lookup *edi *(edi+4))  # Var-name Var-name => eax
24632     (write-buffered *(ebp+0x10) %eax)
24633     (write-buffered *(ebp+0x10) "' does not have the right type\n")
24634     (flush *(ebp+0x10))
24635     (stop *(ebp+0x14) 1)
24636     # never gets here
24637 
24638 check-mu-compute-offset-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
24639     # . prologue
24640     55/push-ebp
24641     89/<- %ebp 4/r32/esp
24642     # . save registers
24643     50/push-eax
24644     51/push-ecx
24645     52/push-edx
24646     53/push-ebx
24647     56/push-esi
24648     57/push-edi
24649     # esi = stmt
24650     8b/-> *(ebp+8) 6/r32/esi
24651     # - check for 0 inouts
24652     # var base/ecx: (addr var) = stmt->inouts->value
24653     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
24654 $check-mu-compute-offset-stmt:check-no-inouts:
24655     3d/compare-eax-and 0/imm32
24656     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-too-few-inouts/disp32
24657     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
24658     89/<- %ecx 0/r32/eax
24659     # - check base type is either (addr array ...) in register or (array ...) on stack
24660     # var base-type/ebx: (addr type-tree) = lookup(base->type)
24661     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
24662     89/<- %ebx 0/r32/eax
24663     # if base-type is an atom, abort with a precise error
24664     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
24665     {
24666       74/jump-if-= break/disp8
24667       (simple-mu-type? %ebx 3)  # array => eax
24668       3d/compare-eax-and 0/imm32/false
24669       0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-base-array-atom-type/disp32
24670       0f 84/jump-if-= $check-mu-compute-offset-stmt:error-base-non-array-type/disp32
24671     }
24672 $check-mu-compute-offset-stmt:base-is-compound:
24673     # if type->left not addr or array, abort
24674     {
24675       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24676       (simple-mu-type? %eax 2)  # addr => eax
24677       3d/compare-eax-and 0/imm32/false
24678       75/jump-if-!= break/disp8
24679       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24680       (simple-mu-type? %eax 3)  # array => eax
24681       3d/compare-eax-and 0/imm32/false
24682       75/jump-if-!= break/disp8
24683       e9/jump $check-mu-compute-offset-stmt:error-base-non-array-type/disp32
24684     }
24685     # if (type->left == addr) ensure type->right->left == array and type->register exists
24686     {
24687       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24688       (simple-mu-type? %eax 2)  # addr => eax
24689       3d/compare-eax-and 0/imm32/false
24690       74/jump-if-= break/disp8
24691 $check-mu-compute-offset-stmt:base-is-addr:
24692       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
24693       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
24694       (simple-mu-type? %eax 3)  # array => eax
24695       3d/compare-eax-and 0/imm32/false
24696       0f 84/jump-if-= $check-mu-compute-offset-stmt:error-base-non-array-type/disp32
24697     }
24698     # if (base-type->left == addr) base-type = base-type->right
24699     {
24700       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24701       (simple-mu-type? %eax 2)  # addr => eax
24702       3d/compare-eax-and 0/imm32/false
24703       74/jump-if-= break/disp8
24704       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
24705       89/<- %ebx 0/r32/eax
24706     }
24707     # - check for 1 inout
24708     # var index/ecx: (addr stmt-var) = stmt->inouts->next->value
24709     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
24710     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
24711 $check-mu-compute-offset-stmt:check-single-inout:
24712     3d/compare-eax-and 0/imm32
24713     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-too-few-inouts/disp32
24714     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
24715     89/<- %ecx 0/r32/eax
24716     # - check index is either a literal or register
24717     # var index-type/edx: (addr type-tree)
24718     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
24719     89/<- %edx 0/r32/eax
24720     # index type must be a literal or int
24721     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
24722     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-invalid-index-type/disp32
24723     {
24724 $check-mu-compute-offset-stmt:index-type-is-atom:
24725       (simple-mu-type? %edx 0)  # literal => eax
24726       3d/compare-eax-and 0/imm32/false
24727       75/jump-if-!= break/disp8
24728       (simple-mu-type? %edx 1)  # int => eax
24729       3d/compare-eax-and 0/imm32/false
24730       75/jump-if-!= break/disp8
24731       e9/jump $check-mu-compute-offset-stmt:error-invalid-index-type/disp32
24732     }
24733     # - check for too many inouts
24734     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
24735     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
24736     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
24737     3d/compare-eax-and 0/imm32/false
24738     0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-too-many-inouts/disp32
24739     # - check for 0 outputs
24740     # var output/edi: (addr var) = stmt->outputs->value
24741     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
24742     3d/compare-eax-and 0/imm32/false
24743     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-too-few-outputs/disp32
24744     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
24745     89/<- %edi 0/r32/eax
24746     # - check output type
24747     # must have a non-atomic type
24748     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
24749     89/<- %edx 0/r32/eax
24750     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
24751     0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-output-type-not-offset/disp32
24752     # type must start with (offset ...)
24753     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
24754     (simple-mu-type? %eax 7)  # offset => eax
24755     3d/compare-eax-and 0/imm32/false
24756     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-output-type-not-offset/disp32
24757     # if tail(base-type) != tail(output-type) abort
24758     (type-tail %ebx)  # => eax
24759     89/<- %ebx 0/r32/eax
24760     (type-tail %edx)  # => eax
24761     (type-equal? %ebx %eax)  # => eax
24762     3d/compare-eax-and 0/imm32/false
24763     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-bad-output-type/disp32
24764     # - check for too many outputs
24765     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
24766     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
24767     3d/compare-eax-and 0/imm32/false
24768     0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-too-many-outputs/disp32
24769 $check-mu-compute-offset-stmt:end:
24770     # . restore registers
24771     5f/pop-to-edi
24772     5e/pop-to-esi
24773     5b/pop-to-ebx
24774     5a/pop-to-edx
24775     59/pop-to-ecx
24776     58/pop-to-eax
24777     # . epilogue
24778     89/<- %esp 5/r32/ebp
24779     5d/pop-to-ebp
24780     c3/return
24781 
24782 $check-mu-compute-offset-stmt:error-base-non-array-type:
24783     (write-buffered *(ebp+0x10) "fn ")
24784     8b/-> *(ebp+0xc) 0/r32/eax
24785     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24786     (write-buffered *(ebp+0x10) %eax)
24787     (write-buffered *(ebp+0x10) ": stmt compute-offset: var '")
24788     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24789     (write-buffered *(ebp+0x10) %eax)
24790     (write-buffered *(ebp+0x10) "' is not an array\n")
24791     (flush *(ebp+0x10))
24792     (stop *(ebp+0x14) 1)
24793     # never gets here
24794 
24795 $check-mu-compute-offset-stmt:error-base-array-atom-type:
24796     (write-buffered *(ebp+0x10) "fn ")
24797     8b/-> *(ebp+0xc) 0/r32/eax
24798     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24799     (write-buffered *(ebp+0x10) %eax)
24800     (write-buffered *(ebp+0x10) ": stmt compute-offset: array '")
24801     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24802     (write-buffered *(ebp+0x10) %eax)
24803     (write-buffered *(ebp+0x10) "' must specify the type of its elements\n")
24804     (flush *(ebp+0x10))
24805     (stop *(ebp+0x14) 1)
24806     # never gets here
24807 
24808 $check-mu-compute-offset-stmt:error-too-few-inouts:
24809     (write-buffered *(ebp+0x10) "fn ")
24810     8b/-> *(ebp+0xc) 0/r32/eax
24811     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24812     (write-buffered *(ebp+0x10) %eax)
24813     (write-buffered *(ebp+0x10) ": stmt compute-offset: too few inouts (2 required)\n")
24814     (flush *(ebp+0x10))
24815     (stop *(ebp+0x14) 1)
24816     # never gets here
24817 
24818 $check-mu-compute-offset-stmt:error-invalid-index-type:
24819     (write-buffered *(ebp+0x10) "fn ")
24820     8b/-> *(ebp+0xc) 0/r32/eax
24821     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24822     (write-buffered *(ebp+0x10) %eax)
24823     (write-buffered *(ebp+0x10) ": stmt compute-offset: second argument '")
24824     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24825     (write-buffered *(ebp+0x10) %eax)
24826     (write-buffered *(ebp+0x10) "' must be an int\n")
24827     (flush *(ebp+0x10))
24828     (stop *(ebp+0x14) 1)
24829     # never gets here
24830 
24831 $check-mu-compute-offset-stmt:error-index-offset-atom-type:
24832     (write-buffered *(ebp+0x10) "fn ")
24833     8b/-> *(ebp+0xc) 0/r32/eax
24834     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24835     (write-buffered *(ebp+0x10) %eax)
24836     (write-buffered *(ebp+0x10) ": stmt compute-offset: offset '")
24837     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24838     (write-buffered *(ebp+0x10) %eax)
24839     (write-buffered *(ebp+0x10) "' must specify the type of array elements\n")
24840     (flush *(ebp+0x10))
24841     (stop *(ebp+0x14) 1)
24842     # never gets here
24843 
24844 $check-mu-compute-offset-stmt:error-index-on-stack:
24845     (write-buffered *(ebp+0x10) "fn ")
24846     8b/-> *(ebp+0xc) 0/r32/eax
24847     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24848     (write-buffered *(ebp+0x10) %eax)
24849     (write-buffered *(ebp+0x10) ": stmt compute-offset: second argument '")
24850     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24851     (write-buffered *(ebp+0x10) %eax)
24852     (write-buffered *(ebp+0x10) "' must be in a register\n")
24853     (flush *(ebp+0x10))
24854     (stop *(ebp+0x14) 1)
24855     # never gets here
24856 
24857 $check-mu-compute-offset-stmt:error-too-many-inouts:
24858     (write-buffered *(ebp+0x10) "fn ")
24859     8b/-> *(ebp+0xc) 0/r32/eax
24860     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24861     (write-buffered *(ebp+0x10) %eax)
24862     (write-buffered *(ebp+0x10) ": stmt compute-offset: too many inouts (2 required)\n")
24863     (flush *(ebp+0x10))
24864     (stop *(ebp+0x14) 1)
24865     # never gets here
24866 
24867 $check-mu-compute-offset-stmt:error-too-few-outputs:
24868     (write-buffered *(ebp+0x10) "fn ")
24869     8b/-> *(ebp+0xc) 0/r32/eax
24870     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24871     (write-buffered *(ebp+0x10) %eax)
24872     (write-buffered *(ebp+0x10) ": stmt compute-offset: must have an output\n")
24873     (flush *(ebp+0x10))
24874     (stop *(ebp+0x14) 1)
24875     # never gets here
24876 
24877 $check-mu-compute-offset-stmt:error-too-many-outputs:
24878     (write-buffered *(ebp+0x10) "fn ")
24879     8b/-> *(ebp+0xc) 0/r32/eax
24880     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24881     (write-buffered *(ebp+0x10) %eax)
24882     (write-buffered *(ebp+0x10) ": stmt compute-offset: too many outputs (1 required)\n")
24883     (flush *(ebp+0x10))
24884     (stop *(ebp+0x14) 1)
24885     # never gets here
24886 
24887 $check-mu-compute-offset-stmt:error-output-not-in-register:
24888     (write-buffered *(ebp+0x10) "fn ")
24889     8b/-> *(ebp+0xc) 0/r32/eax
24890     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24891     (write-buffered *(ebp+0x10) %eax)
24892     (write-buffered *(ebp+0x10) ": stmt compute-offset: output '")
24893     (lookup *edi *(edi+4))  # Var-name Var-name => eax
24894     (write-buffered *(ebp+0x10) %eax)
24895     (write-buffered *(ebp+0x10) "' is not in a register\n")
24896     (flush *(ebp+0x10))
24897     (stop *(ebp+0x14) 1)
24898     # never gets here
24899 
24900 $check-mu-compute-offset-stmt:error-output-type-not-offset:
24901     (write-buffered *(ebp+0x10) "fn ")
24902     8b/-> *(ebp+0xc) 0/r32/eax
24903     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24904     (write-buffered *(ebp+0x10) %eax)
24905     (write-buffered *(ebp+0x10) ": stmt compute-offset: output '")
24906     (lookup *edi *(edi+4))  # Var-name Var-name => eax
24907     (write-buffered *(ebp+0x10) %eax)
24908     (write-buffered *(ebp+0x10) "' must be an offset\n")
24909     (flush *(ebp+0x10))
24910     (stop *(ebp+0x14) 1)
24911     # never gets here
24912 
24913 $check-mu-compute-offset-stmt:error-bad-output-type:
24914     (write-buffered *(ebp+0x10) "fn ")
24915     8b/-> *(ebp+0xc) 0/r32/eax
24916     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24917     (write-buffered *(ebp+0x10) %eax)
24918     (write-buffered *(ebp+0x10) ": stmt compute-offset: output '")
24919     (lookup *edi *(edi+4))  # Var-name Var-name => eax
24920     (write-buffered *(ebp+0x10) %eax)
24921     (write-buffered *(ebp+0x10) "' does not have the right type\n")
24922     (flush *(ebp+0x10))
24923     (stop *(ebp+0x14) 1)
24924     # never gets here
24925 
24926 check-mu-copy-object-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
24927     # . prologue
24928     55/push-ebp
24929     89/<- %ebp 4/r32/esp
24930     # . save registers
24931     50/push-eax
24932     51/push-ecx
24933     53/push-ebx
24934     56/push-esi
24935     57/push-edi
24936     # esi = stmt
24937     8b/-> *(ebp+8) 6/r32/esi
24938 $check-mu-copy-object-stmt:check-for-output:
24939     # if stmt->outputs abort
24940     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
24941     3d/compare-eax-and 0/imm32
24942     0f 85/jump-if-!= $check-mu-copy-object-stmt:error-too-many-outputs/disp32
24943 $check-mu-copy-object-stmt:get-left:
24944     # var dest/edi: (addr stmt-var) = stmt->inouts
24945     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
24946     89/<- %edi 0/r32/eax
24947     # zero inouts
24948     3d/compare-eax-and 0/imm32
24949     0f 84/jump-if-= $check-mu-copy-object-stmt:error-incorrect-inouts/disp32
24950 $check-mu-copy-object-stmt:get-src:
24951     # var src/esi: (addr stmt-var) = dest->next
24952     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
24953     89/<- %esi 0/r32/eax
24954     # 1 inout
24955     3d/compare-eax-and 0/imm32
24956     0f 84/jump-if-= $check-mu-copy-object-stmt:error-incorrect-inouts/disp32
24957     # > 2 inouts
24958     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
24959     3d/compare-eax-and 0/imm32
24960     0f 85/jump-if-!= $check-mu-copy-object-stmt:error-incorrect-inouts/disp32
24961 $check-mu-copy-object-stmt:types:
24962     # var src-type/ecx: (addr type-tree) = src->value->type
24963     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
24964     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
24965     89/<- %ecx 0/r32/eax
24966     # if (src->is-deref?) src-type = src-type->payload
24967     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
24968     3d/compare-eax-and 0/imm32/false
24969     {
24970       74/jump-if-= break/disp8
24971       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
24972       # if src-type->right is null, src-type = src-type->left
24973       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
24974       {
24975         75/jump-if-!= break/disp8
24976         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
24977       }
24978       89/<- %ecx 0/r32/eax
24979     }
24980     # if src-type is not addr, abort
24981     (mu-addr-type? %ecx)  # => eax
24982     3d/compare-eax-and 0/imm32/false
24983     0f 84/jump-if-= $check-mu-copy-object-stmt:error-invalid-types/disp32
24984     # var dest-type/ebx: (addr type-tree) = dest->value->type
24985     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
24986     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
24987     89/<- %ebx 0/r32/eax
24988     # if (dest->is-deref?) dest-type = dest-type->payload
24989     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
24990     3d/compare-eax-and 0/imm32/false
24991     {
24992       74/jump-if-= break/disp8
24993       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
24994       # if dest-type->right is null, dest-type = dest-type->left
24995       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
24996       {
24997         75/jump-if-!= break/disp8
24998         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
24999       }
25000       89/<- %ebx 0/r32/eax
25001     }
25002     # if (dest-type != src-type) abort
25003     (type-equal? %ecx %ebx)  # => eax
25004     3d/compare-eax-and 0/imm32
25005     0f 84/jump-if-= $check-mu-copy-object-stmt:error-invalid-types/disp32
25006 $check-mu-copy-object-stmt:end:
25007     # . restore registers
25008     5f/pop-to-edi
25009     5e/pop-to-esi
25010     5b/pop-to-ebx
25011     59/pop-to-ecx
25012     58/pop-to-eax
25013     # . epilogue
25014     89/<- %esp 5/r32/ebp
25015     5d/pop-to-ebp
25016     c3/return
25017 
25018 $check-mu-copy-object-stmt:error-incorrect-inouts:
25019     (write-buffered *(ebp+0x10) "fn ")
25020     8b/-> *(ebp+0xc) 0/r32/eax
25021     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25022     (write-buffered *(ebp+0x10) %eax)
25023     (write-buffered *(ebp+0x10) ": stmt 'copy-object' must have two inouts\n")
25024     (flush *(ebp+0x10))
25025     (stop *(ebp+0x14) 1)
25026     # never gets here
25027 
25028 $check-mu-copy-object-stmt:error-too-many-outputs:
25029     (write-buffered *(ebp+0x10) "fn ")
25030     8b/-> *(ebp+0xc) 0/r32/eax
25031     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25032     (write-buffered *(ebp+0x10) %eax)
25033     (write-buffered *(ebp+0x10) ": stmt 'copy-object' must not have any outputs\n")
25034     (flush *(ebp+0x10))
25035     (stop *(ebp+0x14) 1)
25036     # never gets here
25037 
25038 $check-mu-copy-object-stmt:error-invalid-types:
25039     (write-buffered *(ebp+0x10) "fn ")
25040     8b/-> *(ebp+0xc) 0/r32/eax
25041     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25042     (write-buffered *(ebp+0x10) %eax)
25043     (write-buffered *(ebp+0x10) ": stmt copy-object: two inouts with identical addr types expected\n")
25044     (flush *(ebp+0x10))
25045     (stop *(ebp+0x14) 1)
25046     # never gets here
25047 
25048 check-mu-clear-object-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
25049     # . prologue
25050     55/push-ebp
25051     89/<- %ebp 4/r32/esp
25052     # . save registers
25053     50/push-eax
25054     51/push-ecx
25055     53/push-ebx
25056     56/push-esi
25057     57/push-edi
25058     # esi = stmt
25059     8b/-> *(ebp+8) 6/r32/esi
25060 $check-mu-clear-object-stmt:check-for-output:
25061     # if stmt->outputs abort
25062     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
25063     3d/compare-eax-and 0/imm32
25064     0f 85/jump-if-!= $check-mu-clear-object-stmt:error-too-many-outputs/disp32
25065 $check-mu-clear-object-stmt:get-left:
25066     # var dest/edi: (addr stmt-var) = stmt->inouts
25067     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25068     89/<- %edi 0/r32/eax
25069     # zero inouts
25070     3d/compare-eax-and 0/imm32
25071     0f 84/jump-if-= $check-mu-clear-object-stmt:error-incorrect-inouts/disp32
25072 $check-mu-clear-object-stmt:get-src:
25073     # > 1 inout
25074     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
25075     3d/compare-eax-and 0/imm32
25076     0f 85/jump-if-!= $check-mu-clear-object-stmt:error-incorrect-inouts/disp32
25077 $check-mu-clear-object-stmt:types:
25078     # var src-type/ecx: (addr type-tree) = src->value->type
25079     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
25080     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
25081     89/<- %ecx 0/r32/eax
25082     # if (src->is-deref?) src-type = src-type->payload
25083     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
25084     3d/compare-eax-and 0/imm32/false
25085     {
25086       74/jump-if-= break/disp8
25087       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
25088       # if src-type->right is null, src-type = src-type->left
25089       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
25090       {
25091         75/jump-if-!= break/disp8
25092         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
25093       }
25094       89/<- %ecx 0/r32/eax
25095     }
25096     # if src-type is not addr, abort
25097     (mu-addr-type? %ecx)  # => eax
25098     3d/compare-eax-and 0/imm32/false
25099     0f 84/jump-if-= $check-mu-clear-object-stmt:error-invalid-type/disp32
25100 $check-mu-clear-object-stmt:end:
25101     # . restore registers
25102     5f/pop-to-edi
25103     5e/pop-to-esi
25104     5b/pop-to-ebx
25105     59/pop-to-ecx
25106     58/pop-to-eax
25107     # . epilogue
25108     89/<- %esp 5/r32/ebp
25109     5d/pop-to-ebp
25110     c3/return
25111 
25112 $check-mu-clear-object-stmt:error-incorrect-inouts:
25113     (write-buffered *(ebp+0x10) "fn ")
25114     8b/-> *(ebp+0xc) 0/r32/eax
25115     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25116     (write-buffered *(ebp+0x10) %eax)
25117     (write-buffered *(ebp+0x10) ": stmt 'clear-object' must have a single inout\n")
25118     (flush *(ebp+0x10))
25119     (stop *(ebp+0x14) 1)
25120     # never gets here
25121 
25122 $check-mu-clear-object-stmt:error-too-many-outputs:
25123     (write-buffered *(ebp+0x10) "fn ")
25124     8b/-> *(ebp+0xc) 0/r32/eax
25125     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25126     (write-buffered *(ebp+0x10) %eax)
25127     (write-buffered *(ebp+0x10) ": stmt 'clear-object' must not have any outputs\n")
25128     (flush *(ebp+0x10))
25129     (stop *(ebp+0x14) 1)
25130     # never gets here
25131 
25132 $check-mu-clear-object-stmt:error-invalid-type:
25133     (write-buffered *(ebp+0x10) "fn ")
25134     8b/-> *(ebp+0xc) 0/r32/eax
25135     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25136     (write-buffered *(ebp+0x10) %eax)
25137     (write-buffered *(ebp+0x10) ": stmt clear-object: inout must have an addr type\n")
25138     (flush *(ebp+0x10))
25139     (stop *(ebp+0x14) 1)
25140     # never gets here
25141 
25142 check-mu-allocate-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
25143     # . prologue
25144     55/push-ebp
25145     89/<- %ebp 4/r32/esp
25146     # . save registers
25147     50/push-eax
25148     53/push-ebx
25149     56/push-esi
25150     57/push-edi
25151     # esi = stmt
25152     8b/-> *(ebp+8) 6/r32/esi
25153 $check-mu-allocate-stmt:check-for-output:
25154     # if stmt->outputs abort
25155     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
25156     3d/compare-eax-and 0/imm32
25157     0f 85/jump-if-!= $check-mu-allocate-stmt:error-too-many-outputs/disp32
25158 $check-mu-allocate-stmt:get-target:
25159     # var target/edi: (addr stmt-var) = stmt->inouts
25160     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25161     89/<- %edi 0/r32/eax
25162     # zero inouts
25163     3d/compare-eax-and 0/imm32
25164     0f 84/jump-if-= $check-mu-allocate-stmt:error-incorrect-inouts/disp32
25165     # > 1 inouts
25166     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
25167     3d/compare-eax-and 0/imm32
25168     0f 85/jump-if-!= $check-mu-allocate-stmt:error-incorrect-inouts/disp32
25169 $check-mu-allocate-stmt:check-type:
25170     # var target-type/ebx: (addr type-tree) = target->value->type
25171     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
25172     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
25173     89/<- %ebx 0/r32/eax
25174     # if (target->is-deref?) target-type = target-type->payload
25175     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
25176     3d/compare-eax-and 0/imm32/false
25177     {
25178       74/jump-if-= break/disp8
25179       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
25180       # if target-type->right is null, target-type = target-type->left
25181       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
25182       {
25183         75/jump-if-!= break/disp8
25184         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
25185       }
25186       89/<- %ebx 0/r32/eax
25187     }
25188     # if target-type is not addr, abort
25189     (mu-addr-type? %ebx)  # => eax
25190     3d/compare-eax-and 0/imm32/false
25191     0f 84/jump-if-= $check-mu-allocate-stmt:error-invalid-type/disp32
25192     # if target-type->right is an atom, abort
25193     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
25194     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
25195     0f 85/jump-if-!= $check-mu-allocate-stmt:error-invalid-type/disp32
25196     # if target-type->right->left is not handle, abort
25197     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
25198     (simple-mu-type? %eax 4)  # handle => eax
25199     3d/compare-eax-and 0/imm32/false
25200     0f 84/jump-if-= $check-mu-allocate-stmt:error-invalid-type/disp32
25201 $check-mu-allocate-stmt:end:
25202     # . restore registers
25203     5f/pop-to-edi
25204     5e/pop-to-esi
25205     5b/pop-to-ebx
25206     58/pop-to-eax
25207     # . epilogue
25208     89/<- %esp 5/r32/ebp
25209     5d/pop-to-ebp
25210     c3/return
25211 
25212 $check-mu-allocate-stmt:error-incorrect-inouts:
25213     (write-buffered *(ebp+0x10) "fn ")
25214     8b/-> *(ebp+0xc) 0/r32/eax
25215     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25216     (write-buffered *(ebp+0x10) %eax)
25217     (write-buffered *(ebp+0x10) ": stmt 'allocate' must have a single inout\n")
25218     (flush *(ebp+0x10))
25219     (stop *(ebp+0x14) 1)
25220     # never gets here
25221 
25222 $check-mu-allocate-stmt:error-too-many-outputs:
25223     (write-buffered *(ebp+0x10) "fn ")
25224     8b/-> *(ebp+0xc) 0/r32/eax
25225     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25226     (write-buffered *(ebp+0x10) %eax)
25227     (write-buffered *(ebp+0x10) ": stmt 'allocate' must not have any outputs\n")
25228     (flush *(ebp+0x10))
25229     (stop *(ebp+0x14) 1)
25230     # never gets here
25231 
25232 $check-mu-allocate-stmt:error-invalid-type:
25233     (write-buffered *(ebp+0x10) "fn ")
25234     8b/-> *(ebp+0xc) 0/r32/eax
25235     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25236     (write-buffered *(ebp+0x10) %eax)
25237     (write-buffered *(ebp+0x10) ": stmt allocate: inout '")
25238     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
25239     (lookup *eax *(eax+4))  # Var-name Var-name => eax
25240     (write-buffered *(ebp+0x10) %eax)
25241     (write-buffered *(ebp+0x10) "' must have type (addr handle ...)\n")
25242     (flush *(ebp+0x10))
25243     (stop *(ebp+0x14) 1)
25244     # never gets here
25245 
25246 check-mu-populate-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
25247     # . prologue
25248     55/push-ebp
25249     89/<- %ebp 4/r32/esp
25250     # . save registers
25251     50/push-eax
25252     53/push-ebx
25253     56/push-esi
25254     57/push-edi
25255     # esi = stmt
25256     8b/-> *(ebp+8) 6/r32/esi
25257 $check-mu-populate-stmt:check-for-output:
25258     # if stmt->outputs abort
25259     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
25260     3d/compare-eax-and 0/imm32
25261     0f 85/jump-if-!= $check-mu-populate-stmt:error-too-many-outputs/disp32
25262 $check-mu-populate-stmt:get-target:
25263     # var target/edi: (addr stmt-var) = stmt->inouts
25264     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25265     89/<- %edi 0/r32/eax
25266     # zero inouts
25267     3d/compare-eax-and 0/imm32
25268     0f 84/jump-if-= $check-mu-populate-stmt:error-incorrect-inouts/disp32
25269 $check-mu-populate-stmt:get-length:
25270     # var length/esi: (addr stmt-var) = dest->next
25271     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
25272     89/<- %esi 0/r32/eax
25273     # 1 inout
25274     3d/compare-eax-and 0/imm32
25275     0f 84/jump-if-= $check-mu-populate-stmt:error-incorrect-inouts/disp32
25276     # > 2 inouts
25277     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
25278     3d/compare-eax-and 0/imm32
25279     0f 85/jump-if-!= $check-mu-populate-stmt:error-incorrect-inouts/disp32
25280 $check-mu-populate-stmt:check-target-type:
25281     # var target-type/ebx: (addr type-tree) = target->value->type
25282     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
25283     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
25284     89/<- %ebx 0/r32/eax
25285 $check-mu-populate-stmt:check-target-type-deref:
25286     # if (target->is-deref?) target-type = target-type->payload
25287     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
25288     3d/compare-eax-and 0/imm32/false
25289     {
25290       74/jump-if-= break/disp8
25291       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
25292       # if target-type->right is null, target-type = target-type->left
25293       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
25294       {
25295         75/jump-if-!= break/disp8
25296         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
25297       }
25298       89/<- %ebx 0/r32/eax
25299     }
25300 $check-mu-populate-stmt:check-target-type-addr:
25301     # if target-type is not addr, abort
25302     (mu-addr-type? %ebx)  # => eax
25303     3d/compare-eax-and 0/imm32/false
25304     0f 84/jump-if-= $check-mu-populate-stmt:error-invalid-target-type/disp32
25305     # if target-type->right is an atom, abort
25306     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
25307     89/<- %ebx 0/r32/eax
25308     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
25309     0f 85/jump-if-!= $check-mu-populate-stmt:error-invalid-target-type/disp32
25310 $check-mu-populate-stmt:check-target-type-handle:
25311     # if target-type->right->left is not handle, abort
25312     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
25313     (simple-mu-type? %eax 4)  # handle => eax
25314     3d/compare-eax-and 0/imm32/false
25315     0f 84/jump-if-= $check-mu-populate-stmt:error-invalid-target-type/disp32
25316     # if target-type->right->right is an atom, abort
25317     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
25318     89/<- %ebx 0/r32/eax
25319     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
25320     0f 85/jump-if-!= $check-mu-populate-stmt:error-invalid-target-type/disp32
25321 $check-mu-populate-stmt:check-target-type-array:
25322     # if target-type->right->right->left is not array, abort
25323     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
25324     (simple-mu-type? %eax 3)  # array => eax
25325     3d/compare-eax-and 0/imm32/false
25326     0f 84/jump-if-= $check-mu-populate-stmt:error-invalid-target-type/disp32
25327 $check-mu-populate-stmt:check-length-type:
25328     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
25329     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
25330     89/<- %ebx 0/r32/eax
25331     (simple-mu-type? %ebx 0)  # literal => eax
25332     3d/compare-eax-and 0/imm32/false
25333     75/jump-if-!= $check-mu-populate-stmt:end/disp8
25334     (simple-mu-type? %ebx 1)  # int => eax
25335     3d/compare-eax-and 0/imm32/false
25336     0f 84/jump-if-= $check-mu-populate-stmt:error-invalid-length-type/disp32
25337 $check-mu-populate-stmt:end:
25338     # . restore registers
25339     5f/pop-to-edi
25340     5e/pop-to-esi
25341     5b/pop-to-ebx
25342     58/pop-to-eax
25343     # . epilogue
25344     89/<- %esp 5/r32/ebp
25345     5d/pop-to-ebp
25346     c3/return
25347 
25348 $check-mu-populate-stmt:error-incorrect-inouts:
25349     (write-buffered *(ebp+0x10) "fn ")
25350     8b/-> *(ebp+0xc) 0/r32/eax
25351     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25352     (write-buffered *(ebp+0x10) %eax)
25353     (write-buffered *(ebp+0x10) ": stmt 'populate' must have two inouts\n")
25354     (flush *(ebp+0x10))
25355     (stop *(ebp+0x14) 1)
25356     # never gets here
25357 
25358 $check-mu-populate-stmt:error-too-many-outputs:
25359     (write-buffered *(ebp+0x10) "fn ")
25360     8b/-> *(ebp+0xc) 0/r32/eax
25361     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25362     (write-buffered *(ebp+0x10) %eax)
25363     (write-buffered *(ebp+0x10) ": stmt 'populate' must not have any outputs\n")
25364     (flush *(ebp+0x10))
25365     (stop *(ebp+0x14) 1)
25366     # never gets here
25367 
25368 $check-mu-populate-stmt:error-invalid-target-type:
25369     (write-buffered *(ebp+0x10) "fn ")
25370     8b/-> *(ebp+0xc) 0/r32/eax
25371     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25372     (write-buffered *(ebp+0x10) %eax)
25373     (write-buffered *(ebp+0x10) ": stmt populate: first inout '")
25374     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
25375     (lookup *eax *(eax+4))  # Var-name Var-name => eax
25376     (write-buffered *(ebp+0x10) %eax)
25377     (write-buffered *(ebp+0x10) "' must have type (addr handle array ...)\n")
25378     (flush *(ebp+0x10))
25379     (stop *(ebp+0x14) 1)
25380     # never gets here
25381 
25382 $check-mu-populate-stmt:error-invalid-length-type:
25383     (write-buffered *(ebp+0x10) "fn ")
25384     8b/-> *(ebp+0xc) 0/r32/eax
25385     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25386     (write-buffered *(ebp+0x10) %eax)
25387     (write-buffered *(ebp+0x10) ": stmt populate: second inout '")
25388     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
25389     (lookup *eax *(eax+4))  # Var-name Var-name => eax
25390     (write-buffered *(ebp+0x10) %eax)
25391     (write-buffered *(ebp+0x10) "' must be an int\n")
25392     (flush *(ebp+0x10))
25393     (stop *(ebp+0x14) 1)
25394     # never gets here
25395 
25396 check-mu-populate-stream-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
25397     # . prologue
25398     55/push-ebp
25399     89/<- %ebp 4/r32/esp
25400     # . save registers
25401     50/push-eax
25402     53/push-ebx
25403     56/push-esi
25404     57/push-edi
25405     # esi = stmt
25406     8b/-> *(ebp+8) 6/r32/esi
25407 $check-mu-populate-stream-stmt:check-for-output:
25408     # if stmt->outputs abort
25409     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
25410     3d/compare-eax-and 0/imm32
25411     0f 85/jump-if-!= $check-mu-populate-stream-stmt:error-too-many-outputs/disp32
25412 $check-mu-populate-stream-stmt:get-target:
25413     # var target/edi: (addr stmt-var) = stmt->inouts
25414     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25415     89/<- %edi 0/r32/eax
25416     # zero inouts
25417     3d/compare-eax-and 0/imm32
25418     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-incorrect-inouts/disp32
25419 $check-mu-populate-stream-stmt:get-length:
25420     # var length/esi: (addr stmt-var) = dest->next
25421     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
25422     89/<- %esi 0/r32/eax
25423     # 1 inout
25424     3d/compare-eax-and 0/imm32
25425     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-incorrect-inouts/disp32
25426     # > 2 inouts
25427     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
25428     3d/compare-eax-and 0/imm32
25429     0f 85/jump-if-!= $check-mu-populate-stream-stmt:error-incorrect-inouts/disp32
25430 $check-mu-populate-stream-stmt:check-target-type:
25431     # var target-type/ebx: (addr type-tree) = target->value->type
25432     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
25433     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
25434     89/<- %ebx 0/r32/eax
25435 $check-mu-populate-stream-stmt:check-target-type-deref:
25436     # if (target->is-deref?) target-type = target-type->payload
25437     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
25438     3d/compare-eax-and 0/imm32/false
25439     {
25440       74/jump-if-= break/disp8
25441       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
25442       # if target-type->right is null, target-type = target-type->left
25443       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
25444       {
25445         75/jump-if-!= break/disp8
25446         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
25447       }
25448       89/<- %ebx 0/r32/eax
25449     }
25450 $check-mu-populate-stream-stmt:check-target-type-addr:
25451     # if target-type is not addr, abort
25452     (mu-addr-type? %ebx)  # => eax
25453     3d/compare-eax-and 0/imm32/false
25454     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
25455     # if target-type->right is an atom, abort
25456     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
25457     89/<- %ebx 0/r32/eax
25458     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
25459     0f 85/jump-if-!= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
25460 $check-mu-populate-stream-stmt:check-target-type-handle:
25461     # if target-type->right->left is not handle, abort
25462     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
25463     (simple-mu-type? %eax 4)  # handle => eax
25464     3d/compare-eax-and 0/imm32/false
25465     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
25466     # if target-type->right->right is an atom, abort
25467     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
25468     89/<- %ebx 0/r32/eax
25469     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
25470     0f 85/jump-if-!= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
25471 $check-mu-populate-stream-stmt:check-target-type-stream:
25472     # if target-type->right->right->left is not stream, abort
25473     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
25474     (simple-mu-type? %eax 0xb)  # stream => eax
25475     3d/compare-eax-and 0/imm32/false
25476     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
25477 $check-mu-populate-stream-stmt:check-length-type:
25478     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
25479     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
25480     89/<- %ebx 0/r32/eax
25481     (simple-mu-type? %ebx 0)  # literal => eax
25482     3d/compare-eax-and 0/imm32/false
25483     75/jump-if-!= $check-mu-populate-stream-stmt:end/disp8
25484     (simple-mu-type? %ebx 1)  # int => eax
25485     3d/compare-eax-and 0/imm32/false
25486     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-invalid-length-type/disp32
25487 $check-mu-populate-stream-stmt:end:
25488     # . restore registers
25489     5f/pop-to-edi
25490     5e/pop-to-esi
25491     5b/pop-to-ebx
25492     58/pop-to-eax
25493     # . epilogue
25494     89/<- %esp 5/r32/ebp
25495     5d/pop-to-ebp
25496     c3/return
25497 
25498 $check-mu-populate-stream-stmt:error-incorrect-inouts:
25499     (write-buffered *(ebp+0x10) "fn ")
25500     8b/-> *(ebp+0xc) 0/r32/eax
25501     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25502     (write-buffered *(ebp+0x10) %eax)
25503     (write-buffered *(ebp+0x10) ": stmt 'populate-stream' must have two inouts\n")
25504     (flush *(ebp+0x10))
25505     (stop *(ebp+0x14) 1)
25506     # never gets here
25507 
25508 $check-mu-populate-stream-stmt:error-too-many-outputs:
25509     (write-buffered *(ebp+0x10) "fn ")
25510     8b/-> *(ebp+0xc) 0/r32/eax
25511     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25512     (write-buffered *(ebp+0x10) %eax)
25513     (write-buffered *(ebp+0x10) ": stmt 'populate-stream' must not have any outputs\n")
25514     (flush *(ebp+0x10))
25515     (stop *(ebp+0x14) 1)
25516     # never gets here
25517 
25518 $check-mu-populate-stream-stmt:error-invalid-target-type:
25519     (write-buffered *(ebp+0x10) "fn ")
25520     8b/-> *(ebp+0xc) 0/r32/eax
25521     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25522     (write-buffered *(ebp+0x10) %eax)
25523     (write-buffered *(ebp+0x10) ": stmt populate-stream: first inout '")
25524     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
25525     (lookup *eax *(eax+4))  # Var-name Var-name => eax
25526     (write-buffered *(ebp+0x10) %eax)
25527     (write-buffered *(ebp+0x10) "' must have type (addr handle stream ...)\n")
25528     (flush *(ebp+0x10))
25529     (stop *(ebp+0x14) 1)
25530     # never gets here
25531 
25532 $check-mu-populate-stream-stmt:error-invalid-length-type:
25533     (write-buffered *(ebp+0x10) "fn ")
25534     8b/-> *(ebp+0xc) 0/r32/eax
25535     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25536     (write-buffered *(ebp+0x10) %eax)
25537     (write-buffered *(ebp+0x10) ": stmt populate-stream: second inout '")
25538     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
25539     (lookup *eax *(eax+4))  # Var-name Var-name => eax
25540     (write-buffered *(ebp+0x10) %eax)
25541     (write-buffered *(ebp+0x10) "' must be an int\n")
25542     (flush *(ebp+0x10))
25543     (stop *(ebp+0x14) 1)
25544     # never gets here
25545 
25546 check-mu-read-from-stream-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
25547     # . prologue
25548     55/push-ebp
25549     89/<- %ebp 4/r32/esp
25550     # . save registers
25551     50/push-eax
25552     51/push-ecx
25553     52/push-edx
25554     53/push-ebx
25555     56/push-esi
25556     57/push-edi
25557     # esi = stmt
25558     8b/-> *(ebp+8) 6/r32/esi
25559     # - check for 0 inouts
25560     # var base/ecx: (addr var) = stmt->inouts->value
25561     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25562 $check-mu-read-from-stream-stmt:check-no-inouts:
25563     3d/compare-eax-and 0/imm32
25564     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-too-few-inouts/disp32
25565     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
25566     89/<- %ecx 0/r32/eax
25567     # - check base type is (addr stream T)
25568     # var base-type/ebx: (addr type-tree) = lookup(base->type)
25569     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
25570     89/<- %ebx 0/r32/eax
25571 $check-mu-read-from-stream-stmt:check-base-is-compound:
25572     # if base-type is an atom, abort
25573     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
25574     0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-invalid-base-type/disp32
25575 $check-mu-read-from-stream-stmt:check-base-is-addr:
25576     # if type->left not addr, abort
25577     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
25578     (simple-mu-type? %eax 2)  # addr => eax
25579     3d/compare-eax-and 0/imm32/false
25580     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-invalid-base-type/disp32
25581 $check-mu-read-from-stream-stmt:check-base-is-addr-to-stream:
25582     # base-type = base-type->right
25583     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
25584     89/<- %ebx 0/r32/eax
25585     # ensure base-type->left == stream
25586     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
25587     (simple-mu-type? %eax 0xb)  # stream => eax
25588     3d/compare-eax-and 0/imm32/false
25589     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-invalid-base-type/disp32
25590     # - check target type is (addr T)
25591     # var target/ecx: (addr stmt-var) = stmt->inouts->next->value
25592     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25593     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
25594 $check-mu-read-from-stream-stmt:check-single-inout:
25595     3d/compare-eax-and 0/imm32
25596     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-too-few-inouts/disp32
25597     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
25598     89/<- %ecx 0/r32/eax
25599     # var target-type/edx: (addr type-tree)
25600     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
25601     89/<- %edx 0/r32/eax
25602     # if target-type is an atom, it must be a literal or int
25603 $check-mu-read-from-stream-stmt:check-target-is-compound:
25604     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
25605     0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-target-type-not-address/disp32
25606 $check-mu-read-from-stream-stmt:check-target-type:
25607     # target type must start with (addr ...)
25608     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
25609     (simple-mu-type? %eax 2)  # addr => eax
25610     3d/compare-eax-and 0/imm32/false
25611     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-target-type-not-address/disp32
25612     # if tail(base-type) != tail(target-type) abort
25613     (type-tail %ebx)  # => eax
25614     89/<- %ebx 0/r32/eax
25615     (type-tail %edx)  # => eax
25616     (type-equal? %ebx %eax)  # => eax
25617     3d/compare-eax-and 0/imm32/false
25618     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-invalid-target-type/disp32
25619 $check-mu-read-from-stream-stmt:check-too-many-inouts:
25620     # - check for too many inouts
25621     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25622     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
25623     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
25624     3d/compare-eax-and 0/imm32/false
25625     0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-too-many-inouts/disp32
25626 $check-mu-read-from-stream-stmt:check-unexpected-output:
25627     # - check for any output
25628     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
25629     3d/compare-eax-and 0/imm32/false
25630     0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-unexpected-output/disp32
25631 $check-mu-read-from-stream-stmt:end:
25632     # . restore registers
25633     5f/pop-to-edi
25634     5e/pop-to-esi
25635     5b/pop-to-ebx
25636     5a/pop-to-edx
25637     59/pop-to-ecx
25638     58/pop-to-eax
25639     # . epilogue
25640     89/<- %esp 5/r32/ebp
25641     5d/pop-to-ebp
25642     c3/return
25643 
25644 $check-mu-read-from-stream-stmt:error-invalid-base-type:
25645     (write-buffered *(ebp+0x10) "fn ")
25646     8b/-> *(ebp+0xc) 0/r32/eax
25647     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25648     (write-buffered *(ebp+0x10) %eax)
25649     (write-buffered *(ebp+0x10) ": stmt read-from-stream: var '")
25650     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
25651     (write-buffered *(ebp+0x10) %eax)
25652     (write-buffered *(ebp+0x10) "' must be an addr to a stream\n")
25653     (flush *(ebp+0x10))
25654     (stop *(ebp+0x14) 1)
25655     # never gets here
25656 
25657 $check-mu-read-from-stream-stmt:error-too-few-inouts:
25658     (write-buffered *(ebp+0x10) "fn ")
25659     8b/-> *(ebp+0xc) 0/r32/eax
25660     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25661     (write-buffered *(ebp+0x10) %eax)
25662     (write-buffered *(ebp+0x10) ": stmt read-from-stream: too few inouts (2 required)\n")
25663     (flush *(ebp+0x10))
25664     (stop *(ebp+0x14) 1)
25665     # never gets here
25666 
25667 $check-mu-read-from-stream-stmt:error-target-type-not-address:
25668     (write-buffered *(ebp+0x10) "fn ")
25669     8b/-> *(ebp+0xc) 0/r32/eax
25670     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25671     (write-buffered *(ebp+0x10) %eax)
25672     (write-buffered *(ebp+0x10) ": stmt read-from-stream: target '")
25673     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
25674     (write-buffered *(ebp+0x10) %eax)
25675     (write-buffered *(ebp+0x10) "' must be an addr\n")
25676     (flush *(ebp+0x10))
25677     (stop *(ebp+0x14) 1)
25678     # never gets here
25679 
25680 $check-mu-read-from-stream-stmt:error-invalid-target-type:
25681     (write-buffered *(ebp+0x10) "fn ")
25682     8b/-> *(ebp+0xc) 0/r32/eax
25683     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25684     (write-buffered *(ebp+0x10) %eax)
25685     (write-buffered *(ebp+0x10) ": stmt read-from-stream: second inout '")
25686     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
25687     (write-buffered *(ebp+0x10) %eax)
25688     (write-buffered *(ebp+0x10) "' does not have the right type\n")
25689     (flush *(ebp+0x10))
25690     (stop *(ebp+0x14) 1)
25691     # never gets here
25692 
25693 $check-mu-read-from-stream-stmt:error-too-many-inouts:
25694     (write-buffered *(ebp+0x10) "fn ")
25695     8b/-> *(ebp+0xc) 0/r32/eax
25696     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25697     (write-buffered *(ebp+0x10) %eax)
25698     (write-buffered *(ebp+0x10) ": stmt read-from-stream: too many inouts (2 required)\n")
25699     (flush *(ebp+0x10))
25700     (stop *(ebp+0x14) 1)
25701     # never gets here
25702 
25703 $check-mu-read-from-stream-stmt:error-unexpected-output:
25704     (write-buffered *(ebp+0x10) "fn ")
25705     8b/-> *(ebp+0xc) 0/r32/eax
25706     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25707     (write-buffered *(ebp+0x10) %eax)
25708     (write-buffered *(ebp+0x10) ": stmt read-from-stream: unexpected output\n")
25709     (flush *(ebp+0x10))
25710     (stop *(ebp+0x14) 1)
25711     # never gets here
25712 
25713 check-mu-write-to-stream-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
25714     # . prologue
25715     55/push-ebp
25716     89/<- %ebp 4/r32/esp
25717     # . save registers
25718     50/push-eax
25719     51/push-ecx
25720     52/push-edx
25721     53/push-ebx
25722     56/push-esi
25723     57/push-edi
25724     # esi = stmt
25725     8b/-> *(ebp+8) 6/r32/esi
25726     # - check for 0 inouts
25727     # var base/ecx: (addr var) = stmt->inouts->value
25728     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25729 $check-mu-write-to-stream-stmt:check-no-inouts:
25730     3d/compare-eax-and 0/imm32
25731     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-too-few-inouts/disp32
25732     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
25733     89/<- %ecx 0/r32/eax
25734     # - check base type is (addr stream T)
25735     # var base-type/ebx: (addr type-tree) = lookup(base->type)
25736     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
25737     89/<- %ebx 0/r32/eax
25738 $check-mu-write-to-stream-stmt:check-base-is-compound:
25739     # if base-type is an atom, abort
25740     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
25741     0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-invalid-base-type/disp32
25742 $check-mu-write-to-stream-stmt:check-base-is-addr:
25743     # if type->left not addr, abort
25744     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
25745     (simple-mu-type? %eax 2)  # addr => eax
25746     3d/compare-eax-and 0/imm32/false
25747     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-invalid-base-type/disp32
25748 $check-mu-write-to-stream-stmt:check-base-is-addr-to-stream:
25749     # base-type = base-type->right
25750     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
25751     89/<- %ebx 0/r32/eax
25752     # ensure base-type->left == stream
25753     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
25754     (simple-mu-type? %eax 0xb)  # stream => eax
25755     3d/compare-eax-and 0/imm32/false
25756     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-invalid-base-type/disp32
25757     # - check target type is (addr T)
25758     # var target/ecx: (addr stmt-var) = stmt->inouts->next->value
25759     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25760     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
25761 $check-mu-write-to-stream-stmt:check-single-inout:
25762     3d/compare-eax-and 0/imm32
25763     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-too-few-inouts/disp32
25764     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
25765     89/<- %ecx 0/r32/eax
25766     # var target-type/edx: (addr type-tree)
25767     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
25768     89/<- %edx 0/r32/eax
25769     # if target-type is an atom, it must be a literal or int
25770 $check-mu-write-to-stream-stmt:check-target-is-compound:
25771     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
25772     0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-target-type-not-address/disp32
25773 $check-mu-write-to-stream-stmt:check-target-type:
25774     # target type must start with (addr ...)
25775     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
25776     (simple-mu-type? %eax 2)  # addr => eax
25777     3d/compare-eax-and 0/imm32/false
25778     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-target-type-not-address/disp32
25779     # if tail(base-type) != tail(target-type) abort
25780     (type-tail %ebx)  # => eax
25781     89/<- %ebx 0/r32/eax
25782     (type-tail %edx)  # => eax
25783     (type-equal? %ebx %eax)  # => eax
25784     3d/compare-eax-and 0/imm32/false
25785     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-invalid-target-type/disp32
25786 $check-mu-write-to-stream-stmt:check-too-many-inouts:
25787     # - check for too many inouts
25788     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25789     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
25790     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
25791     3d/compare-eax-and 0/imm32/false
25792     0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-too-many-inouts/disp32
25793 $check-mu-write-to-stream-stmt:check-unexpected-output:
25794     # - check for any output
25795     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
25796     3d/compare-eax-and 0/imm32/false
25797     0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-unexpected-output/disp32
25798 $check-mu-write-to-stream-stmt:end:
25799     # . restore registers
25800     5f/pop-to-edi
25801     5e/pop-to-esi
25802     5b/pop-to-ebx
25803     5a/pop-to-edx
25804     59/pop-to-ecx
25805     58/pop-to-eax
25806     # . epilogue
25807     89/<- %esp 5/r32/ebp
25808     5d/pop-to-ebp
25809     c3/return
25810 
25811 $check-mu-write-to-stream-stmt:error-invalid-base-type:
25812     (write-buffered *(ebp+0x10) "fn ")
25813     8b/-> *(ebp+0xc) 0/r32/eax
25814     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25815     (write-buffered *(ebp+0x10) %eax)
25816     (write-buffered *(ebp+0x10) ": stmt write-to-stream: var '")
25817     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
25818     (write-buffered *(ebp+0x10) %eax)
25819     (write-buffered *(ebp+0x10) "' must be an addr to a stream\n")
25820     (flush *(ebp+0x10))
25821     (stop *(ebp+0x14) 1)
25822     # never gets here
25823 
25824 $check-mu-write-to-stream-stmt:error-too-few-inouts:
25825     (write-buffered *(ebp+0x10) "fn ")
25826     8b/-> *(ebp+0xc) 0/r32/eax
25827     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25828     (write-buffered *(ebp+0x10) %eax)
25829     (write-buffered *(ebp+0x10) ": stmt write-to-stream: too few inouts (2 required)\n")
25830     (flush *(ebp+0x10))
25831     (stop *(ebp+0x14) 1)
25832     # never gets here
25833 
25834 $check-mu-write-to-stream-stmt:error-target-type-not-address:
25835     (write-buffered *(ebp+0x10) "fn ")
25836     8b/-> *(ebp+0xc) 0/r32/eax
25837     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25838     (write-buffered *(ebp+0x10) %eax)
25839     (write-buffered *(ebp+0x10) ": stmt write-to-stream: target '")
25840     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
25841     (write-buffered *(ebp+0x10) %eax)
25842     (write-buffered *(ebp+0x10) "' must be an addr\n")
25843     (flush *(ebp+0x10))
25844     (stop *(ebp+0x14) 1)
25845     # never gets here
25846 
25847 $check-mu-write-to-stream-stmt:error-invalid-target-type:
25848     (write-buffered *(ebp+0x10) "fn ")
25849     8b/-> *(ebp+0xc) 0/r32/eax
25850     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25851     (write-buffered *(ebp+0x10) %eax)
25852     (write-buffered *(ebp+0x10) ": stmt write-to-stream: second inout '")
25853     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
25854     (write-buffered *(ebp+0x10) %eax)
25855     (write-buffered *(ebp+0x10) "' does not have the right type\n")
25856     (flush *(ebp+0x10))
25857     (stop *(ebp+0x14) 1)
25858     # never gets here
25859 
25860 $check-mu-write-to-stream-stmt:error-too-many-inouts:
25861     (write-buffered *(ebp+0x10) "fn ")
25862     8b/-> *(ebp+0xc) 0/r32/eax
25863     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25864     (write-buffered *(ebp+0x10) %eax)
25865     (write-buffered *(ebp+0x10) ": stmt write-to-stream: too many inouts (2 required)\n")
25866     (flush *(ebp+0x10))
25867     (stop *(ebp+0x14) 1)
25868     # never gets here
25869 
25870 $check-mu-write-to-stream-stmt:error-unexpected-output:
25871     (write-buffered *(ebp+0x10) "fn ")
25872     8b/-> *(ebp+0xc) 0/r32/eax
25873     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25874     (write-buffered *(ebp+0x10) %eax)
25875     (write-buffered *(ebp+0x10) ": stmt write-to-stream: unexpected output\n")
25876     (flush *(ebp+0x10))
25877     (stop *(ebp+0x14) 1)
25878     # never gets here
25879 
25880 check-mu-convert-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
25881     # . prologue
25882     55/push-ebp
25883     89/<- %ebp 4/r32/esp
25884     # . save registers
25885     50/push-eax
25886     51/push-ecx
25887     52/push-edx
25888     56/push-esi
25889     57/push-edi
25890 $check-mu-convert-stmt:get-output:
25891     # esi = stmt
25892     8b/-> *(ebp+8) 6/r32/esi
25893     # var output/edi: (addr stmt-var) = stmt->outputs
25894     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
25895     89/<- %edi 0/r32/eax
25896     # zero outputs
25897     3d/compare-eax-and 0/imm32
25898     0f 84/jump-if-= $check-mu-convert-stmt:error-no-output/disp32
25899     # > 1 output
25900     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
25901     3d/compare-eax-and 0/imm32
25902     0f 85/jump-if-!= $check-mu-convert-stmt:error-too-many-outputs/disp32
25903 $check-mu-convert-stmt:get-inout:
25904     # var inout/esi: (addr stmt-var) = stmt->inouts
25905     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25906     89/<- %esi 0/r32/eax
25907     # zero inouts
25908     3d/compare-eax-and 0/imm32
25909     0f 84/jump-if-= $check-mu-convert-stmt:error-no-inout/disp32
25910     # > 1 inout
25911     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
25912     3d/compare-eax-and 0/imm32
25913     0f 85/jump-if-!= $check-mu-convert-stmt:error-too-many-inouts/disp32
25914 $check-mu-convert-stmt:types:
25915     # var inout-type/ecx: (addr type-tree) = inout->value->type
25916     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
25917     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
25918     89/<- %ecx 0/r32/eax
25919     # if (inout->is-deref?) inout-type = inout-type->payload
25920     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
25921     3d/compare-eax-and 0/imm32/false
25922     {
25923       74/jump-if-= break/disp8
25924       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
25925       # if inout-type->right is null, t = inout-type->left
25926       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
25927       {
25928         75/jump-if-!= break/disp8
25929         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
25930       }
25931       89/<- %ecx 0/r32/eax
25932     }
25933     # if input is not int or float, abort
25934     {
25935       (simple-mu-type? %ecx 1)  # int => eax
25936       3d/compare-eax-and 0/imm32/false
25937       75/jump-if-!= break/disp8
25938       (simple-mu-type? %ecx 0xf)  # float => eax
25939       3d/compare-eax-and 0/imm32/false
25940       75/jump-if-!= break/disp8
25941       e9/jump $check-mu-convert-stmt:error-invalid-inout-type/disp32
25942     }
25943     # if output not in register, abort
25944     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
25945     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
25946     3d/compare-eax-and 0/imm32
25947     0f 84/jump-if-= $check-mu-convert-stmt:error-output-not-in-register/disp32
25948     # var output-type/edx: (addr type-tree) = output->value->type
25949     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
25950     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
25951     89/<- %edx 0/r32/eax
25952     # if output is not int or float, abort
25953     {
25954       (simple-mu-type? %edx 1)  # int => eax
25955       3d/compare-eax-and 0/imm32/false
25956       75/jump-if-!= break/disp8
25957       (simple-mu-type? %edx 0xf)  # float => eax
25958       3d/compare-eax-and 0/imm32/false
25959       75/jump-if-!= break/disp8
25960       e9/jump $check-mu-convert-stmt:error-invalid-output-type/disp32
25961     }
25962     # if both are ints, abort
25963     {
25964       (simple-mu-type? %edx 1)  # int => eax
25965       3d/compare-eax-and 0/imm32/false
25966       74/jump-if-= break/disp8
25967       (simple-mu-type? %ecx 1)  # int => eax
25968       3d/compare-eax-and 0/imm32/false
25969       74/jump-if-= break/disp8
25970       e9/jump $check-mu-convert-stmt:error-int-to-int/disp32
25971     }
25972     # if both are floats, abort
25973     {
25974       (simple-mu-type? %edx 0xf)  # float => eax
25975       3d/compare-eax-and 0/imm32/false
25976       74/jump-if-= break/disp8
25977       (simple-mu-type? %ecx 0xf)  # float => eax
25978       3d/compare-eax-and 0/imm32/false
25979       74/jump-if-= break/disp8
25980       e9/jump $check-mu-convert-stmt:error-float-to-float/disp32
25981     }
25982 $check-mu-convert-stmt:end:
25983     # . restore registers
25984     5f/pop-to-edi
25985     5e/pop-to-esi
25986     5a/pop-to-edx
25987     59/pop-to-ecx
25988     58/pop-to-eax
25989     # . epilogue
25990     89/<- %esp 5/r32/ebp
25991     5d/pop-to-ebp
25992     c3/return
25993 
25994 $check-mu-convert-stmt:error-no-inout:
25995     (write-buffered *(ebp+0x10) "fn ")
25996     8b/-> *(ebp+0xc) 0/r32/eax
25997     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25998     (write-buffered *(ebp+0x10) %eax)
25999     (write-buffered *(ebp+0x10) ": stmt 'convert' expects an inout\n")
26000     (flush *(ebp+0x10))
26001     (stop *(ebp+0x14) 1)
26002     # never gets here
26003 
26004 $check-mu-convert-stmt:error-too-many-inouts:
26005     (write-buffered *(ebp+0x10) "fn ")
26006     8b/-> *(ebp+0xc) 0/r32/eax
26007     (lookup *eax *(eax+4))  # Function-name Function-name => eax
26008     (write-buffered *(ebp+0x10) %eax)
26009     (write-buffered *(ebp+0x10) ": stmt 'convert' must have just one inout\n")
26010     (flush *(ebp+0x10))
26011     (stop *(ebp+0x14) 1)
26012     # never gets here
26013 
26014 $check-mu-convert-stmt:error-no-output:
26015     (write-buffered *(ebp+0x10) "fn ")
26016     8b/-> *(ebp+0xc) 0/r32/eax
26017     (lookup *eax *(eax+4))  # Function-name Function-name => eax
26018     (write-buffered *(ebp+0x10) %eax)
26019     (write-buffered *(ebp+0x10) ": stmt 'convert' expects an output\n")
26020     (flush *(ebp+0x10))
26021     (stop *(ebp+0x14) 1)
26022     # never gets here
26023 
26024 $check-mu-convert-stmt:error-output-not-in-register:
26025     (write-buffered *(ebp+0x10) "fn ")
26026     8b/-> *(ebp+0xc) 0/r32/eax
26027     (lookup *eax *(eax+4))  # Function-name Function-name => eax
26028     (write-buffered *(ebp+0x10) %eax)
26029     (write-buffered *(ebp+0x10) ": stmt convert: output '")
26030     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
26031     (lookup *eax *(eax+4))  # Var-name Var-name => eax
26032     (write-buffered *(ebp+0x10) %eax)
26033     (write-buffered *(ebp+0x10) "' not in a register\n")
26034     (flush *(ebp+0x10))
26035     (stop *(ebp+0x14) 1)
26036     # never gets here
26037 
26038 $check-mu-convert-stmt:error-too-many-outputs:
26039     (write-buffered *(ebp+0x10) "fn ")
26040     8b/-> *(ebp+0xc) 0/r32/eax
26041     (lookup *eax *(eax+4))  # Function-name Function-name => eax
26042     (write-buffered *(ebp+0x10) %eax)
26043     (write-buffered *(ebp+0x10) ": stmt 'convert' must have just one output\n")
26044     (flush *(ebp+0x10))
26045     (stop *(ebp+0x14) 1)
26046     # never gets here
26047 
26048 $check-mu-convert-stmt:error-invalid-inout-type:
26049     (write-buffered *(ebp+0x10) "fn ")
26050     8b/-> *(ebp+0xc) 0/r32/eax
26051     (lookup *eax *(eax+4))  # Function-name Function-name => eax
26052     (write-buffered *(ebp+0x10) %eax)
26053     (write-buffered *(ebp+0x10) ": stmt convert: inout '")
26054     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
26055     (lookup *eax *(eax+4))  # Var-name Var-name => eax
26056     (write-buffered *(ebp+0x10) %eax)
26057     (write-buffered *(ebp+0x10) "' must be an int or float\n")
26058     (flush *(ebp+0x10))
26059     (stop *(ebp+0x14) 1)
26060     # never gets here
26061 
26062 $check-mu-convert-stmt:error-invalid-output-type:
26063     (write-buffered *(ebp+0x10) "fn ")
26064     8b/-> *(ebp+0xc) 0/r32/eax
26065     (lookup *eax *(eax+4))  # Function-name Function-name => eax
26066     (write-buffered *(ebp+0x10) %eax)
26067     (write-buffered *(ebp+0x10) ": stmt convert: output '")
26068     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
26069     (lookup *eax *(eax+4))  # Var-name Var-name => eax
26070     (write-buffered *(ebp+0x10) %eax)
26071     (write-buffered *(ebp+0x10) "' must be an int or float\n")
26072     (flush *(ebp+0x10))
26073     (stop *(ebp+0x14) 1)
26074     # never gets here
26075 
26076 $check-mu-convert-stmt:error-int-to-int:
26077     (write-buffered *(ebp+0x10) "fn ")
26078     8b/-> *(ebp+0xc) 0/r32/eax
26079     (lookup *eax *(eax+4))  # Function-name Function-name => eax
26080     (write-buffered *(ebp+0x10) %eax)
26081     (write-buffered *(ebp+0x10) ": stmt convert: no need to convert int to int\n")
26082     (flush *(ebp+0x10))
26083     (stop *(ebp+0x14) 1)
26084     # never gets here
26085 
26086 $check-mu-convert-stmt:error-float-to-float:
26087     (write-buffered *(ebp+0x10) "fn ")
26088     8b/-> *(ebp+0xc) 0/r32/eax
26089     (lookup *eax *(eax+4))  # Function-name Function-name => eax
26090     (write-buffered *(ebp+0x10) %eax)
26091     (write-buffered *(ebp+0x10) ": stmt convert: no need to convert float to float\n")
26092     (flush *(ebp+0x10))
26093     (stop *(ebp+0x14) 1)
26094     # never gets here
26095 
26096 check-mu-call:  # stmt: (addr stmt), callee: (addr function), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
26097     # . prologue
26098     55/push-ebp
26099     89/<- %ebp 4/r32/esp
26100     # var type-parameters: (addr table (handle array byte) (addr type-tree) 8)
26101     68/push 0/imm32
26102     # var type-parameters-storage: (table (handle array byte) (addr type-tree) 8)
26103     81 5/subop/subtract %esp 0x60/imm32
26104     68/push 0x60/imm32/size
26105     68/push 0/imm32/read
26106     68/push 0/imm32/write
26107     # save a pointer to type-parameters-storage at type-parameters
26108     89/<- *(ebp-4) 4/r32/esp
26109     (clear-stream *(ebp-4))
26110     # . save registers
26111     50/push-eax
26112     51/push-ecx
26113     52/push-edx
26114     53/push-ebx
26115     56/push-esi
26116     57/push-edi
26117     # esi = stmt
26118     8b/-> *(ebp+8) 6/r32/esi
26119     # edi = callee
26120     8b/-> *(ebp+0xc) 7/r32/edi
26121     # var inouts/ecx: (addr stmt-var) = lookup(stmt->inouts)
26122     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
26123     89/<- %ecx 0/r32/eax
26124     # var expected/edx: (addr list var) = lookup(f->inouts)
26125     (lookup *(edi+8) *(edi+0xc))  # Function-inouts Function-inouts => eax
26126     89/<- %edx 0/r32/eax
26127     {
26128 $check-mu-call:check-for-inouts:
26129       # if (inouts == 0) break
26130       81 7/subop/compare %ecx 0/imm32
26131       0f 84/jump-if-= break/disp32
26132       # if (expected == 0) error
26133       81 7/subop/compare %edx 0/imm32
26134       0f 84/jump-if-= break/disp32
26135 $check-mu-call:check-null-addr:
26136       # if (inouts->value->name == "0") continue
26137       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
26138       (lookup *eax *(eax+4))  # Var-name Var-name => eax
26139       (string-equal? %eax "0")  # => eax
26140       3d/compare-eax-and 0/imm32/false
26141       0f 85/jump-if-!= $check-mu-call:continue-to-next-inout/disp32
26142 $check-mu-call:check-inout-type:
26143       # var t/ebx: (addr type-tree) = inouts->value->type
26144       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
26145       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
26146       89/<- %ebx 0/r32/eax
26147       # if (inouts->is-deref?) t = t->right
26148       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
26149       {
26150         74/jump-if-= break/disp8
26151         (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
26152         89/<- %ebx 0/r32/eax
26153         # if t->right is null, t = t->left
26154         81 7/subop/compare *(ebx+0xc) 0/imm32  # Type-tree-right
26155         75/jump-if-!= break/disp8
26156         (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
26157         89/<- %ebx 0/r32/eax
26158       }
26159       # var v2/eax: (addr v) = lookup(expected->value)
26160       (lookup *edx *(edx+4))  # List-value List-value => eax
26161       # var t2/eax: (addr type-tree) = lookup(v2->type)
26162       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
26163       # if (t != t2) error
26164       (type-match? %eax %ebx *(ebp-4))  # => eax
26165       3d/compare-eax-and 0/imm32/false
26166       {
26167         0f 85/jump-if-!= break/disp32
26168         (write-buffered *(ebp+0x14) "fn ")
26169         8b/-> *(ebp+0x10) 0/r32/eax
26170         (lookup *eax *(eax+4))  # Function-name Function-name => eax
26171         (write-buffered *(ebp+0x14) %eax)
26172         (write-buffered *(ebp+0x14) ": call ")
26173         (lookup *edi *(edi+4))  # Function-name Function-name => eax
26174         (write-buffered *(ebp+0x14) %eax)
26175         (write-buffered *(ebp+0x14) ": type for inout '")
26176         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
26177         (lookup *eax *(eax+4))  # Var-name Var-name => eax
26178         (write-buffered *(ebp+0x14) %eax)
26179         (write-buffered *(ebp+0x14) "' is not right\n")
26180         (flush *(ebp+0x14))
26181         (stop *(ebp+0x18) 1)
26182       }
26183 $check-mu-call:continue-to-next-inout:
26184       # inouts = lookup(inouts->next)
26185       (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
26186       89/<- %ecx 0/r32/eax
26187       # expected = lookup(expected->next)
26188       (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
26189       89/<- %edx 0/r32/eax
26190       #
26191       e9/jump loop/disp32
26192     }
26193 $check-mu-call:check-inout-count:
26194     # if (inouts == expected) proceed
26195     39/compare %ecx 2/r32/edx
26196     {
26197       0f 84/jump-if-= break/disp32
26198       # exactly one of the two is null
26199       # if (inouts == 0) error("too many inouts")
26200       {
26201         81 7/subop/compare %ecx 0/imm32
26202         0f 84/jump-if-= break/disp32
26203         (write-buffered *(ebp+0x14) "fn ")
26204         8b/-> *(ebp+0x10) 0/r32/eax
26205         (lookup *eax *(eax+4))  # Function-name Function-name => eax
26206         (write-buffered *(ebp+0x14) %eax)
26207         (write-buffered *(ebp+0x14) ": call ")
26208         (lookup *edi *(edi+4))  # Function-name Function-name => eax
26209         (write-buffered *(ebp+0x14) %eax)
26210         (write-buffered *(ebp+0x14) ": too many inouts\n")
26211         (flush *(ebp+0x14))
26212         (stop *(ebp+0x18) 1)
26213       }
26214       # if (expected == 0) error("too few inouts")
26215       {
26216         81 7/subop/compare %edx 0/imm32
26217         0f 84/jump-if-= break/disp32
26218         (write-buffered *(ebp+0x14) "fn ")
26219         8b/-> *(ebp+0x10) 0/r32/eax
26220         (lookup *eax *(eax+4))  # Function-name Function-name => eax
26221         (write-buffered *(ebp+0x14) %eax)
26222         (write-buffered *(ebp+0x14) ": call ")
26223         (lookup *edi *(edi+4))  # Function-name Function-name => eax
26224         (write-buffered *(ebp+0x14) %eax)
26225         (write-buffered *(ebp+0x14) ": too few inouts\n")
26226         (flush *(ebp+0x14))
26227         (stop *(ebp+0x18) 1)
26228       }
26229     }
26230 $check-mu-call:check-outputs:
26231     # var outputs/ecx: (addr stmt-var) = lookup(stmt->outputs)
26232     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
26233     89/<- %ecx 0/r32/eax
26234     # var expected/edx: (addr list var) = lookup(f->outputs)
26235     (lookup *(edi+0x10) *(edi+0x14))  # Function-outputs Function-outputs => eax
26236     89/<- %edx 0/r32/eax
26237     {
26238 $check-mu-call:check-for-outputs:
26239       # if (outputs == 0) break
26240       81 7/subop/compare %ecx 0/imm32
26241       0f 84/jump-if-= break/disp32
26242       # if (expected == 0) error
26243       81 7/subop/compare %edx 0/imm32
26244       0f 84/jump-if-= break/disp32
26245 $check-mu-call:check-output-type:
26246       # var v/eax: (addr v) = lookup(outputs->value)
26247       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
26248       # var t/ebx: (addr type-tree) = lookup(v->type)
26249       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
26250       89/<- %ebx 0/r32/eax
26251       # if (outputs->is-deref?) t = t->right  # TODO: check that t->left is an addr
26252       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
26253       {
26254         74/jump-if-= break/disp8
26255         (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
26256         89/<- %ebx 0/r32/eax
26257       }
26258       # var v2/eax: (addr v) = lookup(expected->value)
26259       (lookup *edx *(edx+4))  # List-value List-value => eax
26260       # var t2/eax: (addr type-tree) = lookup(v2->type)
26261       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
26262       # if (t != t2) error
26263       (type-match? %eax %ebx *(ebp-4))  # => eax
26264       3d/compare-eax-and 0/imm32/false
26265       {
26266         0f 85/jump-if-!= break/disp32
26267         (write-buffered *(ebp+0x14) "fn ")
26268         8b/-> *(ebp+0x10) 0/r32/eax
26269         (lookup *eax *(eax+4))  # Function-name Function-name => eax
26270         (write-buffered *(ebp+0x14) %eax)
26271         (write-buffered *(ebp+0x14) ": call ")
26272         (lookup *edi *(edi+4))  # Function-name Function-name => eax
26273         (write-buffered *(ebp+0x14) %eax)
26274         (write-buffered *(ebp+0x14) ": type for output '")
26275         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
26276         (lookup *eax *(eax+4))  # Var-name Var-name => eax
26277         (write-buffered *(ebp+0x14) %eax)
26278         (write-buffered *(ebp+0x14) "' is not right\n")
26279         (flush *(ebp+0x14))
26280         (stop *(ebp+0x18) 1)
26281       }
26282 $check-mu-call:check-output-register:
26283       # var v/eax: (addr v) = lookup(outputs->value)
26284       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
26285       # var r/ebx: (addr array byte) = lookup(v->register)
26286       (lookup *(eax+18) *(eax+0x1c))  # Var-register Var-register => eax
26287       89/<- %ebx 0/r32/eax
26288       # if (r == 0) error
26289       3d/compare-eax-and 0/imm32
26290       {
26291         0f 85/jump-if-!= break/disp32
26292         (write-buffered *(ebp+0x14) "fn ")
26293         8b/-> *(ebp+0x10) 0/r32/eax
26294         (lookup *eax *(eax+4))  # Function-name Function-name => eax
26295         (write-buffered *(ebp+0x14) %eax)
26296         (write-buffered *(ebp+0x14) ": call ")
26297         (lookup *edi *(edi+4))  # Function-name Function-name => eax
26298         (write-buffered *(ebp+0x14) %eax)
26299         (write-buffered *(ebp+0x14) ": output '")
26300         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
26301         (lookup *eax *(eax+4))  # Var-name Var-name => eax
26302         (write-buffered *(ebp+0x14) %eax)
26303         (write-buffered *(ebp+0x14) "' is not in a register\n")
26304         (flush *(ebp+0x14))
26305         (stop *(ebp+0x18) 1)
26306       }
26307       # var v2/eax: (addr v) = lookup(expected->value)
26308       (lookup *edx *(edx+4))  # Stmt-var-value Stmt-var-value => eax
26309       # var r2/eax: (addr array byte) = lookup(v2->register)
26310       (lookup *(eax+18) *(eax+0x1c))  # Var-register Var-register => eax
26311       # if (r != r2) error
26312       (string-equal? %eax %ebx)  # => eax
26313       3d/compare-eax-and 0/imm32/false
26314       {
26315         0f 85/jump-if-!= break/disp32
26316         (write-buffered *(ebp+0x14) "fn ")
26317         8b/-> *(ebp+0x10) 0/r32/eax
26318         (lookup *eax *(eax+4))  # Function-name Function-name => eax
26319         (write-buffered *(ebp+0x14) %eax)
26320         (write-buffered *(ebp+0x14) ": call ")
26321         (lookup *edi *(edi+4))  # Function-name Function-name => eax
26322         (write-buffered *(ebp+0x14) %eax)
26323         (write-buffered *(ebp+0x14) ": register for output '")
26324         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
26325         (lookup *eax *(eax+4))  # Var-name Var-name => eax
26326         (write-buffered *(ebp+0x14) %eax)
26327         (write-buffered *(ebp+0x14) "' is not right\n")
26328         (flush *(ebp+0x14))
26329         (stop *(ebp+0x18) 1)
26330       }
26331 $check-mu-call:continue-to-next-output:
26332       # outputs = lookup(outputs->next)
26333       (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
26334       89/<- %ecx 0/r32/eax
26335       # expected = lookup(expected->next)
26336       (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
26337       89/<- %edx 0/r32/eax
26338       #
26339       e9/jump loop/disp32
26340     }
26341 $check-mu-call:check-output-count:
26342     # if (outputs == expected) proceed
26343     39/compare %ecx 2/r32/edx
26344     {
26345       0f 84/jump-if-= break/disp32
26346       # exactly one of the two is null
26347       # if (outputs == 0) error("too many outputs")
26348       {
26349         81 7/subop/compare %ecx 0/imm32
26350         0f 84/jump-if-= break/disp32
26351         (write-buffered *(ebp+0x14) "fn ")
26352         8b/-> *(ebp+0x10) 0/r32/eax
26353         (lookup *eax *(eax+4))  # Function-name Function-name => eax
26354         (write-buffered *(ebp+0x14) %eax)
26355         (write-buffered *(ebp+0x14) ": call ")
26356         (lookup *edi *(edi+4))  # Function-name Function-name => eax
26357         (write-buffered *(ebp+0x14) %eax)
26358         (write-buffered *(ebp+0x14) ": too many outputs\n")
26359         (flush *(ebp+0x14))
26360         (stop *(ebp+0x18) 1)
26361       }
26362       # if (expected == 0) error("too few outputs")
26363       {
26364         81 7/subop/compare %edx 0/imm32
26365         0f 84/jump-if-= break/disp32
26366         (write-buffered *(ebp+0x14) "fn ")
26367         8b/-> *(ebp+0x10) 0/r32/eax
26368         (lookup *eax *(eax+4))  # Function-name Function-name => eax
26369         (write-buffered *(ebp+0x14) %eax)
26370         (write-buffered *(ebp+0x14) ": call ")
26371         (lookup *edi *(edi+4))  # Function-name Function-name => eax
26372         (write-buffered *(ebp+0x14) %eax)
26373         (write-buffered *(ebp+0x14) ": too few outputs\n")
26374         (flush *(ebp+0x14))
26375         (stop *(ebp+0x18) 1)
26376       }
26377     }
26378 $check-mu-call:end:
26379     # . restore registers
26380     5f/pop-to-edi
26381     5e/pop-to-esi
26382     5b/pop-to-ebx
26383     5a/pop-to-edx
26384     59/pop-to-ecx
26385     58/pop-to-eax
26386     # . reclaim locals exclusively on the stack
26387     81 0/subop/add %esp 0x70/imm32
26388     # . epilogue
26389     89/<- %esp 5/r32/ebp
26390     5d/pop-to-ebp
26391     c3/return
26392 
26393 # like type-equal? but takes literals type parameters into account
26394 type-match?:  # def: (addr type-tree), call: (addr type-tree), type-parameters: (addr table (handle array byte) (addr type-tree)) -> result/eax: boolean
26395     # . prologue
26396     55/push-ebp
26397     89/<- %ebp 4/r32/esp
26398     # if (call is literal and def is numberlike) return true
26399     {
26400 $type-match?:check-literal-int:
26401       (simple-mu-type? *(ebp+0xc) 0)  # literal => eax
26402       3d/compare-eax-and 0/imm32/false
26403       74/jump-if-= break/disp8
26404       (mu-numberlike-output? *(ebp+8))  # => eax
26405       3d/compare-eax-and 0/imm32/false
26406       74/jump-if-= break/disp8
26407       b8/copy-to-eax 1/imm32/true
26408       e9/jump $type-match?:end/disp32
26409     }
26410     # if (call is literal-string and def is string) return true
26411     {
26412 $type-match?:check-literal-string:
26413       (simple-mu-type? *(ebp+0xc) 0x10)  # literal-string => eax
26414       3d/compare-eax-and 0/imm32/false
26415       74/jump-if-= break/disp8
26416       (mu-string-type? *(ebp+8))  # => eax
26417       3d/compare-eax-and 0/imm32/false
26418       74/jump-if-= break/disp8
26419       b8/copy-to-eax 1/imm32/true
26420       e9/jump $type-match?:end/disp32
26421     }
26422 $type-match?:baseline:
26423     # otherwise fall back
26424     (type-component-match? *(ebp+8) *(ebp+0xc) *(ebp+0x10))  # => eax
26425 $type-match?:end:
26426     # . epilogue
26427     89/<- %esp 5/r32/ebp
26428     5d/pop-to-ebp
26429     c3/return
26430 
26431 type-component-match?:  # def: (addr type-tree), call: (addr type-tree), type-parameters: (addr table (handle array byte) (addr type-tree)) -> result/eax: boolean
26432     # . prologue
26433     55/push-ebp
26434     89/<- %ebp 4/r32/esp
26435     # . save registers
26436     51/push-ecx
26437     52/push-edx
26438     53/push-ebx
26439     # ecx = def
26440     8b/-> *(ebp+8) 1/r32/ecx
26441     # edx = call
26442     8b/-> *(ebp+0xc) 2/r32/edx
26443 $type-component-match?:compare-addr:
26444     # if (def == call) return true
26445     8b/-> %ecx 0/r32/eax  # Var-type
26446     39/compare %edx 0/r32/eax  # Var-type
26447     b8/copy-to-eax 1/imm32/true
26448     0f 84/jump-if-= $type-component-match?:end/disp32
26449     # if (def == 0) return false
26450     b8/copy-to-eax 0/imm32/false
26451     81 7/subop/compare %ecx 0/imm32  # Type-tree-is-atom
26452     0f 84/jump-if-= $type-component-match?:end/disp32
26453     # if (call == 0) return false
26454     81 7/subop/compare %edx 0/imm32  # Type-tree-is-atom
26455     0f 84/jump-if-= $type-component-match?:end/disp32
26456     # if def is a type parameter, just check in type-parameters
26457     {
26458 $type-component-match?:check-type-parameter:
26459       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
26460       74/jump-if-= break/disp8
26461       81 7/subop/compare *(ecx+4) 0xa/imm32/type-parameter  # Type-tree-value
26462       75/jump-if-!= break/disp8
26463 $type-component-match?:type-parameter:
26464       (type-parameter-match? *(ecx+8) *(ecx+0xc)  %edx  *(ebp+0x10))  # => eax
26465       e9/jump $type-component-match?:end/disp32
26466     }
26467     # if def is a list containing just a type parameter, just check in type-parameters
26468     {
26469 $type-component-match?:check-list-type-parameter:
26470       # if def is a list..
26471       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
26472       75/jump-if-!= break/disp8
26473       #   ..that's a singleton
26474       81 7/subop/compare *(ecx+0xc) 0/imm32  # Type-tree-left
26475       75/jump-if-!= break/disp8
26476       #   ..and whose head is a type parameter
26477       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
26478       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
26479       74/jump-if-= break/disp8
26480       81 7/subop/compare *(eax+4) 0xa/imm32/type-parameter  # Type-tree-value
26481       75/jump-if-!= break/disp8
26482 $type-component-match?:list-type-parameter:
26483       (type-parameter-match? *(eax+8) *(eax+0xc)  %edx  *(ebp+0x10))  # => eax
26484       e9/jump $type-component-match?:end/disp32
26485     }
26486 $type-component-match?:compare-atom-state:
26487     # if (def->is-atom? != call->is-atom?) return false
26488     8b/-> *ecx 3/r32/ebx  # Type-tree-is-atom
26489     39/compare *edx 3/r32/ebx  # Type-tree-is-atom
26490     b8/copy-to-eax 0/imm32/false
26491     0f 85/jump-if-!= $type-component-match?:end/disp32
26492     # if def->is-atom? return (def->value == call->value)
26493     {
26494 $type-component-match?:check-atom:
26495       81 7/subop/compare %ebx 0/imm32/false
26496       74/jump-if-= break/disp8
26497 $type-component-match?:is-atom:
26498       8b/-> *(ecx+4) 0/r32/eax  # Type-tree-value
26499       39/compare *(edx+4) 0/r32/eax  # Type-tree-value
26500       0f 94/set-if-= %al
26501       81 4/subop/and %eax 0xff/imm32
26502       e9/jump $type-component-match?:end/disp32
26503     }
26504 $type-component-match?:check-left:
26505     # if (!type-component-match?(def->left, call->left)) return false
26506     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
26507     89/<- %ebx 0/r32/eax
26508     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
26509     (type-component-match? %ebx %eax *(ebp+0x10))  # => eax
26510     3d/compare-eax-and 0/imm32/false
26511     74/jump-if-= $type-component-match?:end/disp8
26512 $type-component-match?:check-right:
26513     # return type-component-match?(def->right, call->right)
26514     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
26515     89/<- %ebx 0/r32/eax
26516     (lookup *(edx+0xc) *(edx+0x10))  # Type-tree-right Type-tree-right => eax
26517     (type-component-match? %ebx %eax *(ebp+0x10))  # => eax
26518 $type-component-match?:end:
26519     # . restore registers
26520     5b/pop-to-ebx
26521     5a/pop-to-edx
26522     59/pop-to-ecx
26523     # . epilogue
26524     89/<- %esp 5/r32/ebp
26525     5d/pop-to-ebp
26526     c3/return
26527 
26528 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
26529     # . prologue
26530     55/push-ebp
26531     89/<- %ebp 4/r32/esp
26532     # . save registers
26533     51/push-ecx
26534     #
26535     (get-or-insert-handle *(ebp+0x14)  *(ebp+8) *(ebp+0xc)  0xc)  # => eax
26536     # if parameter wasn't saved, save it
26537     {
26538       81 7/subop/compare *eax 0/imm32
26539       75/jump-if-!= break/disp8
26540       8b/-> *(ebp+0x10) 1/r32/ecx
26541       89/<- *eax 1/r32/ecx
26542     }
26543     #
26544     (type-equal? *(ebp+0x10) *eax)  # => eax
26545 $type-parameter-match?:end:
26546     # . restore registers
26547     59/pop-to-ecx
26548     # . epilogue
26549     89/<- %esp 5/r32/ebp
26550     5d/pop-to-ebp
26551     c3/return
26552 
26553 size-of:  # v: (addr var) -> result/eax: int
26554     # . prologue
26555     55/push-ebp
26556     89/<- %ebp 4/r32/esp
26557     # . save registers
26558     51/push-ecx
26559     # var t/ecx: (addr type-tree) = lookup(v->type)
26560     8b/-> *(ebp+8) 1/r32/ecx
26561 #?     (write-buffered Stderr "size-of ")
26562 #?     (write-int32-hex-buffered Stderr %ecx)
26563 #?     (write-buffered Stderr Newline)
26564 #?     (write-buffered Stderr "type allocid: ")
26565 #?     (write-int32-hex-buffered Stderr *(ecx+8))
26566 #?     (write-buffered Stderr Newline)
26567 #?     (flush Stderr)
26568     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
26569     89/<- %ecx 0/r32/eax
26570     # if mu-array?(t) return size-of-array(t)
26571     {
26572       (mu-array? %ecx)  # => eax
26573       3d/compare-eax-and 0/imm32/false
26574       74/jump-if-= break/disp8
26575       (size-of-array %ecx)  # => eax
26576       eb/jump $size-of:end/disp8
26577     }
26578     # if mu-stream?(t) return size-of-stream(t)
26579     {
26580       (mu-stream? %ecx)  # => eax
26581       3d/compare-eax-and 0/imm32/false
26582       74/jump-if-= break/disp8
26583       (size-of-stream %ecx)  # => eax
26584       eb/jump $size-of:end/disp8
26585     }
26586     # if (!t->is-atom?) t = lookup(t->left)
26587     {
26588       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
26589       75/jump-if-!= break/disp8
26590       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
26591       89/<- %ecx 0/r32/eax
26592     }
26593     # TODO: assert t->is-atom?
26594     (size-of-type-id *(ecx+4))  # Type-tree-value => eax
26595 $size-of:end:
26596     # . restore registers
26597     59/pop-to-ecx
26598     # . epilogue
26599     89/<- %esp 5/r32/ebp
26600     5d/pop-to-ebp
26601     c3/return
26602 
26603 size-of-deref:  # v: (addr var) -> result/eax: int
26604     # . prologue
26605     55/push-ebp
26606     89/<- %ebp 4/r32/esp
26607     # . save registers
26608     51/push-ecx
26609     # var t/ecx: (addr type-tree) = lookup(v->type)
26610     8b/-> *(ebp+8) 1/r32/ecx
26611     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
26612     89/<- %ecx 0/r32/eax
26613     # TODO: assert(t is an addr)
26614     # t = lookup(t->right)
26615     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
26616     89/<- %ecx 0/r32/eax
26617     # if mu-array?(t) return size-of-array(t)
26618     {
26619       (mu-array? %ecx)  # => eax
26620       3d/compare-eax-and 0/imm32/false
26621       74/jump-if-= break/disp8
26622       (size-of-array %ecx)  # => eax
26623       eb/jump $size-of-deref:end/disp8
26624     }
26625     # if mu-stream?(t) return size-of-stream(t)
26626     {
26627       (mu-stream? %ecx)  # => eax
26628       3d/compare-eax-and 0/imm32/false
26629       74/jump-if-= break/disp8
26630       (size-of-stream %ecx)  # => eax
26631       eb/jump $size-of-deref:end/disp8
26632     }
26633     # if (!t->is-atom?) t = lookup(t->left)
26634     {
26635       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
26636       75/jump-if-!= break/disp8
26637       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
26638       89/<- %ecx 0/r32/eax
26639     }
26640     # TODO: assert t->is-atom?
26641     (size-of-type-id *(ecx+4))  # Type-tree-value => eax
26642 $size-of-deref:end:
26643     # . restore registers
26644     59/pop-to-ecx
26645     # . epilogue
26646     89/<- %esp 5/r32/ebp
26647     5d/pop-to-ebp
26648     c3/return
26649 
26650 mu-array?:  # t: (addr type-tree) -> result/eax: boolean
26651     # . prologue
26652     55/push-ebp
26653     89/<- %ebp 4/r32/esp
26654     # . save registers
26655     51/push-ecx
26656     # ecx = t
26657     8b/-> *(ebp+8) 1/r32/ecx
26658     # if t->is-atom?, return false
26659     81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
26660     75/jump-if-!= $mu-array?:return-false/disp8
26661     # if !t->left->is-atom?, return false
26662     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
26663     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
26664     74/jump-if-= $mu-array?:return-false/disp8
26665     # return t->left->value == array
26666     81 7/subop/compare *(eax+4) 3/imm32/array-type-id  # Type-tree-value
26667     0f 94/set-if-= %al
26668     81 4/subop/and %eax 0xff/imm32
26669     eb/jump $mu-array?:end/disp8
26670 $mu-array?:return-false:
26671     b8/copy-to-eax 0/imm32/false
26672 $mu-array?:end:
26673     # . restore registers
26674     59/pop-to-ecx
26675     # . epilogue
26676     89/<- %esp 5/r32/ebp
26677     5d/pop-to-ebp
26678     c3/return
26679 
26680 # size of a statically allocated array where the size is part of the type expression
26681 size-of-array:  # a: (addr type-tree) -> result/eax: int
26682     # . prologue
26683     55/push-ebp
26684     89/<- %ebp 4/r32/esp
26685     # . save registers
26686     51/push-ecx
26687     52/push-edx
26688     #
26689     8b/-> *(ebp+8) 1/r32/ecx
26690     # TODO: assert that a->left is 'array'
26691     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
26692     89/<- %ecx 0/r32/eax
26693     # var elem-type/edx: type-id = a->right->left->value
26694     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
26695     8b/-> *(eax+4) 2/r32/edx  # Type-tree-value
26696     # TODO: assert that a->right->right->left->value == size
26697     # var array-size/ecx: int = a->right->right->left->value-size
26698     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
26699     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
26700     8b/-> *(eax+8) 1/r32/ecx  # Type-tree-value-size
26701     # return 4 + array-size * size-of(elem-type)
26702     (size-of-type-id-as-array-element %edx)  # => eax
26703     f7 4/subop/multiply-into-edx-eax %ecx
26704     05/add-to-eax 4/imm32  # for array size
26705     # TODO: check edx for overflow
26706 $size-of-array:end:
26707     # . restore registers
26708     5a/pop-to-edx
26709     59/pop-to-ecx
26710     # . epilogue
26711     89/<- %esp 5/r32/ebp
26712     5d/pop-to-ebp
26713     c3/return
26714 
26715 mu-stream?:  # t: (addr type-tree) -> result/eax: boolean
26716     # . prologue
26717     55/push-ebp
26718     89/<- %ebp 4/r32/esp
26719     # . save registers
26720     51/push-ecx
26721     # ecx = t
26722     8b/-> *(ebp+8) 1/r32/ecx
26723     # if t->is-atom?, return false
26724     81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
26725     75/jump-if-!= $mu-stream?:return-false/disp8
26726     # if !t->left->is-atom?, return false
26727     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
26728     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
26729     74/jump-if-= $mu-stream?:return-false/disp8
26730     # return t->left->value == stream
26731     81 7/subop/compare *(eax+4) 0xb/imm32/stream-type-id  # Type-tree-value
26732     0f 94/set-if-= %al
26733     81 4/subop/and %eax 0xff/imm32
26734     eb/jump $mu-stream?:end/disp8
26735 $mu-stream?:return-false:
26736     b8/copy-to-eax 0/imm32/false
26737 $mu-stream?:end:
26738     # . restore registers
26739     59/pop-to-ecx
26740     # . epilogue
26741     89/<- %esp 5/r32/ebp
26742     5d/pop-to-ebp
26743     c3/return
26744 
26745 # size of a statically allocated stream where the size is part of the type expression
26746 size-of-stream:  # a: (addr type-tree) -> result/eax: int
26747     # . prologue
26748     55/push-ebp
26749     89/<- %ebp 4/r32/esp
26750     #
26751     (size-of-array *(ebp+8))  # assumes we ignore the actual type name 'array' in the type
26752     05/add-to-eax 8/imm32  # for read/write pointers
26753 $size-of-stream:end:
26754     # . epilogue
26755     89/<- %esp 5/r32/ebp
26756     5d/pop-to-ebp
26757     c3/return
26758 
26759 size-of-type-id:  # t: type-id -> result/eax: int
26760     # . prologue
26761     55/push-ebp
26762     89/<- %ebp 4/r32/esp
26763     # . save registers
26764     51/push-ecx
26765     # var out/ecx: (handle typeinfo)
26766     68/push 0/imm32
26767     68/push 0/imm32
26768     89/<- %ecx 4/r32/esp
26769     # eax = t
26770     8b/-> *(ebp+8) 0/r32/eax
26771     # if t is a literal, return 0
26772     3d/compare-eax-and 0/imm32
26773     0f 84/jump-if-= $size-of-type-id:end/disp32  # eax changes type from type-id to int
26774     # if t is a byte, return 4 (because we don't really support non-multiples of 4)
26775     3d/compare-eax-and 8/imm32/byte
26776     {
26777       75/jump-if-!= break/disp8
26778       b8/copy-to-eax 4/imm32
26779       eb/jump $size-of-type-id:end/disp8
26780     }
26781     # if t is a handle, return 8
26782     3d/compare-eax-and 4/imm32/handle
26783     {
26784       75/jump-if-!= break/disp8
26785       b8/copy-to-eax 8/imm32
26786       eb/jump $size-of-type-id:end/disp8  # eax changes type from type-id to int
26787     }
26788     # if t is a slice, return 8
26789     3d/compare-eax-and 0xc/imm32/slice
26790     {
26791       75/jump-if-!= break/disp8
26792       b8/copy-to-eax 8/imm32
26793       eb/jump $size-of-type-id:end/disp8  # eax changes type from type-id to int
26794     }
26795     # if t is a user-defined type, return its size
26796     # TODO: support non-atom type
26797     (find-typeinfo %eax %ecx)
26798     {
26799       81 7/subop/compare *ecx 0/imm32
26800       74/jump-if-= break/disp8
26801 $size-of-type-id:user-defined:
26802       (lookup *ecx *(ecx+4))  # => eax
26803       8b/-> *(eax+0xc) 0/r32/eax  # Typeinfo-total-size-in-bytes
26804       eb/jump $size-of-type-id:end/disp8
26805     }
26806     # otherwise return the word size
26807     b8/copy-to-eax 4/imm32
26808 $size-of-type-id:end:
26809     # . reclaim locals
26810     81 0/subop/add %esp 8/imm32
26811     # . restore registers
26812     59/pop-to-ecx
26813     # . epilogue
26814     89/<- %esp 5/r32/ebp
26815     5d/pop-to-ebp
26816     c3/return
26817 
26818 # Minor violation of our type system since it returns an addr. But we could
26819 # replace it with a handle some time.
26820 # Returns null if t is an atom.
26821 type-tail:  # t: (addr type-tree) -> out/eax: (addr type-tree)
26822     # . prologue
26823     55/push-ebp
26824     89/<- %ebp 4/r32/esp
26825     # . save registers
26826     51/push-ecx
26827     # eax = 0
26828     b8/copy-to-eax 0/imm32
26829     # ecx = t
26830     8b/-> *(ebp+8) 1/r32/ecx
26831 $type-tail:check-atom:
26832     # if t->is-atom? return 0
26833     81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
26834     0f 85/jump-if-!= $type-tail:end/disp32
26835     # var tail = t->right
26836     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
26837     89/<- %ecx 0/r32/eax
26838 $type-tail:check-singleton:
26839     # if (tail->right == 0) return tail->left
26840     {
26841       81 7/subop/compare *(ecx+0xc) 0/imm32  # Type-tree-right
26842       75/jump-if-!= break/disp8
26843       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
26844       e9/jump $type-tail:end/disp32
26845     }
26846     # if tail->right->left is an array-capacity, return tail->left
26847     {
26848 $type-tail:check-array-capacity:
26849       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
26850       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
26851       75/jump-if-!= break/disp8
26852 $type-tail:check-array-capacity-1:
26853       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
26854       3d/compare-eax-and 0/imm32
26855       74/jump-if-= break/disp8
26856 $type-tail:check-array-capacity-2:
26857       (simple-mu-type? %eax 9)  # array-capacity => eax
26858       3d/compare-eax-and 0/imm32/false
26859       74/jump-if-= break/disp8
26860 $type-tail:array-capacity:
26861       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
26862       eb/jump $type-tail:end/disp8
26863     }
26864 $type-tail:check-compound-left:
26865     # if !tail->left->is-atom? return tail->left
26866     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
26867     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
26868     74/jump-if-= $type-tail:end/disp8
26869 $type-tail:return-tail:
26870     # return tail
26871     89/<- %eax 1/r32/ecx
26872 $type-tail:end:
26873     # . restore registers
26874     59/pop-to-ecx
26875     # . epilogue
26876     89/<- %esp 5/r32/ebp
26877     5d/pop-to-ebp
26878     c3/return
26879 
26880 type-equal?:  # a: (addr type-tree), b: (addr type-tree) -> result/eax: boolean
26881     # . prologue
26882     55/push-ebp
26883     89/<- %ebp 4/r32/esp
26884     # . save registers
26885     51/push-ecx
26886     52/push-edx
26887     53/push-ebx
26888     # ecx = a
26889     8b/-> *(ebp+8) 1/r32/ecx
26890     # edx = b
26891     8b/-> *(ebp+0xc) 2/r32/edx
26892 $type-equal?:compare-addr:
26893     # if (a == b) return true
26894     8b/-> %ecx 0/r32/eax  # Var-type
26895     39/compare %edx 0/r32/eax  # Var-type
26896     b8/copy-to-eax 1/imm32/true
26897     0f 84/jump-if-= $type-equal?:end/disp32
26898 $type-equal?:compare-null-a:
26899     # if (a == 0) return false
26900     b8/copy-to-eax 0/imm32/false
26901     81 7/subop/compare %ecx 0/imm32
26902     0f 84/jump-if-= $type-equal?:end/disp32
26903 $type-equal?:compare-null-b:
26904     # if (b == 0) return false
26905     81 7/subop/compare %edx 0/imm32
26906     0f 84/jump-if-= $type-equal?:end/disp32
26907 $type-equal?:compare-atom-state:
26908     # if (a->is-atom? != b->is-atom?) return false
26909     8b/-> *ecx 3/r32/ebx  # Type-tree-is-atom
26910     39/compare *edx 3/r32/ebx  # Type-tree-is-atom
26911     b8/copy-to-eax 0/imm32/false
26912     0f 85/jump-if-!= $type-equal?:end/disp32
26913     # if a->is-atom? return (a->value == b->value)
26914     {
26915 $type-equal?:check-atom:
26916       81 7/subop/compare %ebx 0/imm32/false
26917       74/jump-if-= break/disp8
26918 $type-equal?:is-atom:
26919       8b/-> *(ecx+4) 0/r32/eax  # Type-tree-value
26920       39/compare *(edx+4) 0/r32/eax  # Type-tree-value
26921       0f 94/set-if-= %al
26922       81 4/subop/and %eax 0xff/imm32
26923       e9/jump $type-equal?:end/disp32
26924     }
26925 $type-equal?:check-left:
26926     # if (!type-equal?(a->left, b->left)) return false
26927     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
26928     89/<- %ebx 0/r32/eax
26929     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
26930     (type-equal? %eax %ebx)  # => eax
26931     3d/compare-eax-and 0/imm32/false
26932     74/jump-if-= $type-equal?:end/disp8
26933 $type-equal?:check-right:
26934     # return type-equal?(a->right, b->right)
26935     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
26936     89/<- %ebx 0/r32/eax
26937     (lookup *(edx+0xc) *(edx+0x10))  # Type-tree-right Type-tree-right => eax
26938     (type-equal? %eax %ebx)  # => eax
26939 $type-equal?:end:
26940     # . restore registers
26941     5b/pop-to-ebx
26942     5a/pop-to-edx
26943     59/pop-to-ecx
26944     # . epilogue
26945     89/<- %esp 5/r32/ebp
26946     5d/pop-to-ebp
26947     c3/return
26948 
26949 #######################################################
26950 # Code-generation
26951 #######################################################
26952 
26953 == data
26954 
26955 # Global state added to each var record when performing code-generation.
26956 Curr-local-stack-offset:  # (addr int)
26957     0/imm32
26958 
26959 == code
26960 
26961 # We may not need to pass err/ed everywhere here. I think they're relics of Mu
26962 # getting type checks later in life.
26963 # But we do need them for runtime checks, particularly array index bounds checks.
26964 # So perhaps it's not worth taking them out. They're a safety net.
26965 
26966 emit-subx:  # out: (addr buffered-file), err: (addr buffered-file), ed: (addr exit-descriptor)
26967     # . prologue
26968     55/push-ebp
26969     89/<- %ebp 4/r32/esp
26970     # . save registers
26971     50/push-eax
26972     # var curr/eax: (addr function) = *Program->functions
26973     (lookup *_Program-functions *_Program-functions->payload)  # => eax
26974     {
26975       # if (curr == null) break
26976       3d/compare-eax-and 0/imm32
26977       0f 84/jump-if-= break/disp32
26978       (emit-subx-function *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10))
26979       # curr = lookup(curr->next)
26980       (lookup *(eax+0x20) *(eax+0x24))  # Function-next Function-next => eax
26981       e9/jump loop/disp32
26982     }
26983 $emit-subx:end:
26984     # . restore registers
26985     58/pop-to-eax
26986     # . epilogue
26987     89/<- %esp 5/r32/ebp
26988     5d/pop-to-ebp
26989     c3/return
26990 
26991 emit-subx-function:  # out: (addr buffered-file), f: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
26992     # . prologue
26993     55/push-ebp
26994     89/<- %ebp 4/r32/esp
26995     # some preprocessing
26996     (populate-mu-type-offsets-in-inouts *(ebp+0xc))
26997     # . save registers
26998     50/push-eax
26999     51/push-ecx
27000     52/push-edx
27001     # initialize some global state
27002     c7 0/subop/copy *Curr-block-depth 1/imm32  # Important: keep this in sync with the parse phase
27003     c7 0/subop/copy *Curr-local-stack-offset 0/imm32
27004     # ecx = f
27005     8b/-> *(ebp+0xc) 1/r32/ecx
27006     # var vars/edx: (stack (addr var) 256)
27007     81 5/subop/subtract %esp 0xc00/imm32
27008     68/push 0xc00/imm32/size
27009     68/push 0/imm32/top
27010     89/<- %edx 4/r32/esp
27011     # var name/eax: (addr array byte) = lookup(f->name)
27012     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
27013     #
27014     (write-buffered *(ebp+8) %eax)
27015     (write-buffered *(ebp+8) ":\n")
27016     (emit-subx-prologue *(ebp+8))
27017     # var body/eax: (addr block) = lookup(f->body)
27018     (lookup *(ecx+0x18) *(ecx+0x1c))  # Function-body Function-body => eax
27019     #
27020     (emit-subx-block *(ebp+8) %eax %edx *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
27021     (emit-subx-epilogue *(ebp+8))
27022     # TODO: validate that *Curr-block-depth and *Curr-local-stack-offset have
27023     # been cleaned up
27024 $emit-subx-function:end:
27025     # . reclaim locals
27026     81 0/subop/add %esp 0xc08/imm32
27027     # . restore registers
27028     5a/pop-to-edx
27029     59/pop-to-ecx
27030     58/pop-to-eax
27031     # . epilogue
27032     89/<- %esp 5/r32/ebp
27033     5d/pop-to-ebp
27034     c3/return
27035 
27036 populate-mu-type-offsets-in-inouts:  # f: (addr function)
27037     # . prologue
27038     55/push-ebp
27039     89/<- %ebp 4/r32/esp
27040     # . save registers
27041     50/push-eax
27042     51/push-ecx
27043     52/push-edx
27044     53/push-ebx
27045     57/push-edi
27046     # var next-offset/edx: int = 8
27047     ba/copy-to-edx 8/imm32
27048     # var curr/ecx: (addr list var) = lookup(f->inouts)
27049     8b/-> *(ebp+8) 1/r32/ecx
27050     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
27051     89/<- %ecx 0/r32/eax
27052     {
27053 $populate-mu-type-offsets-in-inouts:loop:
27054       81 7/subop/compare %ecx 0/imm32
27055       74/jump-if-= break/disp8
27056       # var v/ebx: (addr var) = lookup(curr->value)
27057       (lookup *ecx *(ecx+4))  # List-value List-value => eax
27058       89/<- %ebx 0/r32/eax
27059 #?       (lookup *ebx *(ebx+4))
27060 #?       (write-buffered Stderr "setting offset of fn inout ")
27061 #?       (write-buffered Stderr %eax)
27062 #?       (write-buffered Stderr "@")
27063 #?       (write-int32-hex-buffered Stderr %ebx)
27064 #?       (write-buffered Stderr " to ")
27065 #?       (write-int32-hex-buffered Stderr %edx)
27066 #?       (write-buffered Stderr Newline)
27067 #?       (flush Stderr)
27068       # v->offset = next-offset
27069       89/<- *(ebx+0x14) 2/r32/edx  # Var-offset
27070       # next-offset += size-of(v)
27071       (size-of %ebx)  # => eax
27072       01/add-to %edx 0/r32/eax
27073       # curr = lookup(curr->next)
27074       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
27075       89/<- %ecx 0/r32/eax
27076       #
27077       eb/jump loop/disp8
27078     }
27079 $populate-mu-type-offsets-in-inouts:end:
27080     # . restore registers
27081     5f/pop-to-edi
27082     5b/pop-to-ebx
27083     5a/pop-to-edx
27084     59/pop-to-ecx
27085     58/pop-to-eax
27086     # . epilogue
27087     89/<- %esp 5/r32/ebp
27088     5d/pop-to-ebp
27089     c3/return
27090 
27091 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)
27092     # . prologue
27093     55/push-ebp
27094     89/<- %ebp 4/r32/esp
27095     # . save registers
27096     50/push-eax
27097     51/push-ecx
27098     53/push-ebx
27099     56/push-esi
27100     # esi = stmts
27101     8b/-> *(ebp+0xc) 6/r32/esi
27102     #
27103     {
27104 $emit-subx-stmt-list:loop:
27105       81 7/subop/compare %esi 0/imm32
27106       0f 84/jump-if-= break/disp32
27107       # var curr-stmt/ecx: (addr stmt) = lookup(stmts->value)
27108       (lookup *esi *(esi+4))  # List-value List-value => eax
27109       89/<- %ecx 0/r32/eax
27110       {
27111 $emit-subx-stmt-list:check-for-block:
27112         81 7/subop/compare *ecx 0/imm32/block  # Stmt-tag
27113         75/jump-if-!= break/disp8
27114 $emit-subx-stmt-list:block:
27115         (emit-subx-block *(ebp+8) %ecx *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
27116       }
27117       {
27118 $emit-subx-stmt-list:check-for-stmt:
27119         81 7/subop/compare *ecx 1/imm32/stmt1  # Stmt-tag
27120         0f 85/jump-if-!= break/disp32
27121 $emit-subx-stmt-list:stmt1:
27122         {
27123           (mu-branch? %ecx)  # => eax
27124           3d/compare-eax-and 0/imm32/false
27125           0f 84/jump-if-= break/disp32
27126 $emit-subx-stmt-list:branch-stmt:
27127 +-- 25 lines: # unconditional return ----------------------------------------------------------------------------------------------------------------------------------------------------
27152 +-- 27 lines: # unconditional loops -----------------------------------------------------------------------------------------------------------------------------------------------------
27179 +-- 16 lines: # unconditional breaks ----------------------------------------------------------------------------------------------------------------------------------------------------
27195 +-- 38 lines: # simple conditional branches without a target ----------------------------------------------------------------------------------------------------------------------------
27233 +-- 19 lines: # conditional branches with an explicit target ----------------------------------------------------------------------------------------------------------------------------
27252         }
27253 $emit-subx-stmt-list:1-to-1:
27254         (emit-subx-stmt *(ebp+8) %ecx Primitives *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
27255         e9/jump $emit-subx-stmt-list:continue/disp32
27256       }
27257       {
27258 $emit-subx-stmt-list:check-for-var-def:
27259         81 7/subop/compare *ecx 2/imm32/var-def  # Stmt-tag
27260         75/jump-if-!= break/disp8
27261 $emit-subx-stmt-list:var-def:
27262         (emit-subx-var-def *(ebp+8) %ecx *(ebp+0x18) *(ebp+0x1c))
27263         (push *(ebp+0x10) *(ecx+4))  # Vardef-var
27264         (push *(ebp+0x10) *(ecx+8))  # Vardef-var
27265         (push *(ebp+0x10) 0)  # Live-var-register-spilled = 0 for vars on the stack
27266         #
27267         eb/jump $emit-subx-stmt-list:continue/disp8
27268       }
27269       {
27270 $emit-subx-stmt-list:check-for-reg-var-def:
27271         81 7/subop/compare *ecx 3/imm32/reg-var-def  # Stmt-tag
27272         0f 85/jump-if-!= break/disp32
27273 $emit-subx-stmt-list:reg-var-def:
27274         # TODO: ensure that there's exactly one output
27275         (push-output-and-maybe-emit-spill *(ebp+8) %ecx *(ebp+0x10) %esi *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
27276         # emit the instruction as usual
27277         (emit-subx-stmt *(ebp+8) %ecx Primitives *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
27278         #
27279         eb/jump $emit-subx-stmt-list:continue/disp8
27280       }
27281 $emit-subx-stmt-list:continue:
27282       # TODO: raise an error on unrecognized Stmt-tag
27283       (lookup *(esi+8) *(esi+0xc))  # List-next List-next => eax
27284       89/<- %esi 0/r32/eax
27285       e9/jump loop/disp32
27286     }
27287 $emit-subx-stmt-list:emit-cleanup:
27288     (emit-cleanup-code-until-depth *(ebp+8) *(ebp+0x10) *Curr-block-depth)
27289 $emit-subx-stmt-list:clean-up:
27290     (clean-up-stack-offset-state *(ebp+0x10) *Curr-block-depth)
27291     (clean-up-blocks *(ebp+0x10) *Curr-block-depth *(ebp+0x14))
27292 $emit-subx-stmt-list:end:
27293     # . restore registers
27294     5e/pop-to-esi
27295     5b/pop-to-ebx
27296     59/pop-to-ecx
27297     58/pop-to-eax
27298     # . epilogue
27299     89/<- %esp 5/r32/ebp
27300     5d/pop-to-ebp
27301     c3/return
27302 
27303 # 'later-stmts' includes 'stmt', but will behave the same even without it; reg-var-def stmts are guaranteed not to write to function outputs.
27304 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)
27305     # . prologue
27306     55/push-ebp
27307     89/<- %ebp 4/r32/esp
27308     # . save registers
27309     50/push-eax
27310     51/push-ecx
27311     52/push-edx
27312     # ecx = stmt
27313     8b/-> *(ebp+0xc) 1/r32/ecx
27314     # var sv/eax: (addr stmt-var) = lookup(curr-stmt->outputs)
27315     (lookup *(ecx+0x14) *(ecx+0x18))  # Regvardef-outputs Regvardef-outputs => eax
27316     # TODO: assert !sv->is-deref?
27317     # var v/ecx: (addr var) = lookup(sv->value)
27318     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
27319     89/<- %ecx 0/r32/eax
27320     # v->block-depth = *Curr-block-depth
27321     8b/-> *Curr-block-depth 0/r32/eax
27322     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
27323 #?     (write-buffered Stderr "var ")
27324 #?     (lookup *ecx *(ecx+4))
27325 #?     (write-buffered Stderr %eax)
27326 #?     (write-buffered Stderr " at depth ")
27327 #?     (write-int32-hex-buffered Stderr *(ecx+0x10))
27328 #?     (write-buffered Stderr Newline)
27329 #?     (flush Stderr)
27330     # ensure that v is in a register
27331     81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
27332     0f 84/jump-if-= $push-output-and-maybe-emit-spill:abort/disp32
27333     # var emit-spill?/edx: boolean = not-yet-spilled-this-block? && will-not-write-some-register?(fn)
27334     (not-yet-spilled-this-block? %ecx *(ebp+0x10))  # => eax
27335     89/<- %edx 0/r32/eax
27336     3d/compare-eax-and 0/imm32/false
27337     0f 84/jump-if-= $push-output-and-maybe-emit-spill:push/disp32
27338     (will-not-write-some-register? %ecx *(ebp+0x14) *(ebp+0x18))  # => eax
27339     89/<- %edx 0/r32/eax
27340     # check emit-spill?
27341     3d/compare-eax-and 0/imm32/false
27342     0f 84/jump-if-= $push-output-and-maybe-emit-spill:push/disp32
27343     # TODO: assert(size-of(output) == 4)
27344     # *Curr-local-stack-offset -= 4
27345     81 5/subop/subtract *Curr-local-stack-offset 4/imm32
27346     # emit spill
27347     (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
27348     (emit-push-register *(ebp+8) %eax)
27349 $push-output-and-maybe-emit-spill:push:
27350     8b/-> *(ebp+0xc) 1/r32/ecx
27351     (lookup *(ecx+0x14) *(ecx+0x18))  # Regvardef-outputs Regvardef-outputs => eax
27352     # push(vars, {sv->value, emit-spill?})
27353     (push *(ebp+0x10) *eax)  # Stmt-var-value
27354     (push *(ebp+0x10) *(eax+4))  # Stmt-var-value
27355     (push *(ebp+0x10) %edx)
27356 $push-output-and-maybe-emit-spill:end:
27357     # . restore registers
27358     5a/pop-to-edx
27359     59/pop-to-ecx
27360     58/pop-to-eax
27361     # . epilogue
27362     89/<- %esp 5/r32/ebp
27363     5d/pop-to-ebp
27364     c3/return
27365 
27366 $push-output-and-maybe-emit-spill:abort:
27367     # error("var '" var->name "' initialized from an instruction must live in a register\n")
27368     (write-buffered *(ebp+0x1c) "var '")
27369     (write-buffered *(ebp+0x1c) *eax)  # Var-name
27370     (write-buffered *(ebp+0x1c) "' initialized from an instruction must live in a register\n")
27371     (flush *(ebp+0x1c))
27372     (stop *(ebp+0x20) 1)
27373     # never gets here
27374 
27375 emit-subx-cleanup-and-unconditional-nonlocal-branch:  # out: (addr buffered-file), stmt: (addr stmt1), vars: (addr stack live-var)
27376     # . prologue
27377     55/push-ebp
27378     89/<- %ebp 4/r32/esp
27379     # . save registers
27380     50/push-eax
27381     51/push-ecx
27382     # ecx = stmt
27383     8b/-> *(ebp+0xc) 1/r32/ecx
27384     # var target/eax: (addr array byte) = curr-stmt->inouts->value->name
27385     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
27386     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
27387     (lookup *eax *(eax+4))  # Var-name Var-name => eax
27388     # clean up until target block
27389     (emit-cleanup-code-until-target *(ebp+8) *(ebp+0x10) %eax)
27390     # emit jump to target block
27391     (emit-indent *(ebp+8) *Curr-block-depth)
27392     (write-buffered *(ebp+8) "e9/jump ")
27393     (write-buffered *(ebp+8) %eax)
27394     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
27395     (string-starts-with? %eax "break")
27396     3d/compare-eax-and 0/imm32/false
27397     {
27398       74/jump-if-= break/disp8
27399       (write-buffered *(ebp+8) ":break/disp32\n")
27400       eb/jump $emit-subx-cleanup-and-unconditional-nonlocal-branch:end/disp8
27401     }
27402     (write-buffered *(ebp+8) ":loop/disp32\n")
27403 $emit-subx-cleanup-and-unconditional-nonlocal-branch:end:
27404     # . restore registers
27405     59/pop-to-ecx
27406     58/pop-to-eax
27407     # . epilogue
27408     89/<- %esp 5/r32/ebp
27409     5d/pop-to-ebp
27410     c3/return
27411 
27412 emit-outputs:  # out: (addr buffered-file), return-stmt: (addr stmt1), fn: (addr function)
27413     # . prologue
27414     55/push-ebp
27415     89/<- %ebp 4/r32/esp
27416     # . save registers
27417     50/push-eax
27418     51/push-ecx
27419     56/push-esi
27420     57/push-edi
27421     # var curr-inout/esi: (addr stmt-var) = return-stmt->inouts
27422     8b/-> *(ebp+0xc) 0/r32/eax
27423     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
27424     89/<- %esi 0/r32/eax
27425     # var curr-output/edi: (addr list var) = fn->outputs
27426     8b/-> *(ebp+0x10) 0/r32/eax
27427     (lookup *(eax+0x10) *(eax+0x14))  # Function-outputs Function-outputs => eax
27428     89/<- %edi 0/r32/eax
27429     {
27430 $emit-outputs:loop:
27431       81 7/subop/compare %esi 0/imm32
27432       0f 84/jump-if-= break/disp32
27433       # emit copy to output register
27434       # var curr-output-register/ecx: (addr array byte) = curr-output->value->register
27435       (lookup *edi *(edi+4))  # List-value List-value => eax
27436       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
27437       89/<- %ecx 0/r32/eax
27438       # if curr-output-register starts with "x", emit a floating-point copy
27439       8a/copy-byte *(ecx+4) 0/r32/AL
27440       81 4/subop/and %eax 0xff/imm32
27441       3d/compare-eax-and 0x78/imm32/x
27442       {
27443         75/jump-if-!= break/disp8
27444         (emit-float-output *(ebp+8) %esi %ecx)
27445         eb/jump $emit-outputs:continue/disp8
27446       }
27447       # otherwise emit an int copy
27448       (emit-int-output *(ebp+8) %esi %ecx)
27449 $emit-outputs:continue:
27450       # curr-inout = curr-inout->next
27451       (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
27452       89/<- %esi 0/r32/eax
27453       # curr-output = curr-output->next
27454       (lookup *(edi+8) *(edi+0xc))  # List-next List-next => eax
27455       89/<- %edi 0/r32/eax
27456       #
27457       e9/jump loop/disp32
27458     }
27459 $emit-outputs:end:
27460     # . restore registers
27461     5f/pop-to-edi
27462     5e/pop-to-esi
27463     59/pop-to-ecx
27464     58/pop-to-eax
27465     # . epilogue
27466     89/<- %esp 5/r32/ebp
27467     5d/pop-to-ebp
27468     c3/return
27469 
27470 emit-int-output:  # out: (addr buffered-file), return-var: (addr stmt-var), dest-reg: (addr array byte)
27471     # . prologue
27472     55/push-ebp
27473     89/<- %ebp 4/r32/esp
27474     # . save registers
27475     50/push-eax
27476     51/push-ecx
27477     # ecx = return-var->value
27478     8b/-> *(ebp+0xc) 0/r32/eax
27479     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
27480     89/<- %ecx 0/r32/eax
27481     # if curr-var is a literal, emit copy of a literal to the output
27482     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
27483     (simple-mu-type? %eax 0)  # literal => eax
27484     {
27485       3d/compare-eax-and 0/imm32/false
27486       0f 84/jump-if-= break/disp32
27487       (emit-indent *(ebp+8) *Curr-block-depth)
27488       (write-buffered *(ebp+8) "c7 0/subop/copy %")
27489       (write-buffered *(ebp+8) *(ebp+0x10))
27490       (write-buffered *(ebp+8) " ")
27491       (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
27492       (write-buffered *(ebp+8) %eax)
27493       (write-buffered *(ebp+8) "/imm32\n")
27494       e9/jump $emit-int-output:end/disp32
27495     }
27496     # otherwise emit an integer copy
27497     (emit-indent *(ebp+8) *Curr-block-depth)
27498     (write-buffered *(ebp+8) "8b/->")
27499     (emit-subx-var-as-rm32 *(ebp+8) *(ebp+0xc))
27500     (write-buffered *(ebp+8) " ")
27501     (get Mu-registers *(ebp+0x10) 0xc "Mu-registers")  # => eax
27502     (write-int32-hex-buffered *(ebp+8) *eax)
27503     (write-buffered *(ebp+8) "/r32\n")
27504 $emit-int-output:end:
27505     # . restore registers
27506     59/pop-to-ecx
27507     58/pop-to-eax
27508     # . epilogue
27509     89/<- %esp 5/r32/ebp
27510     5d/pop-to-ebp
27511     c3/return
27512 
27513 emit-float-output:  # out: (addr buffered-file), return-var: (addr stmt-var), dest-reg: (addr array byte)
27514     # . prologue
27515     55/push-ebp
27516     89/<- %ebp 4/r32/esp
27517     # . save registers
27518     50/push-eax
27519     #
27520     (emit-indent *(ebp+8) *Curr-block-depth)
27521     (write-buffered *(ebp+8) "f3 0f 10/->")
27522     (emit-subx-var-as-rm32 *(ebp+8) *(ebp+0xc))
27523     (write-buffered *(ebp+8) " ")
27524     (get Mu-registers *(ebp+0x10) 0xc "Mu-registers")  # => eax
27525     (write-int32-hex-buffered *(ebp+8) *eax)
27526     (write-buffered *(ebp+8) "/x32\n")
27527 $emit-float-output:end:
27528     # . restore registers
27529     58/pop-to-eax
27530     # . epilogue
27531     89/<- %esp 5/r32/ebp
27532     5d/pop-to-ebp
27533     c3/return
27534 
27535 mu-branch?:  # stmt: (addr stmt1) -> result/eax: boolean
27536     # . prologue
27537     55/push-ebp
27538     89/<- %ebp 4/r32/esp
27539     # . save registers
27540     51/push-ecx
27541     # ecx = lookup(stmt->operation)
27542     8b/-> *(ebp+8) 1/r32/ecx
27543     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
27544     89/<- %ecx 0/r32/eax
27545     # if (stmt->operation starts with "loop") return true
27546     (string-starts-with? %ecx "loop")  # => eax
27547     3d/compare-eax-and 0/imm32/false
27548     75/jump-if-not-equal $mu-branch?:end/disp8
27549     # if (stmt->operation starts with "break") return true
27550     (string-starts-with? %ecx "break")  # => eax
27551     3d/compare-eax-and 0/imm32/false
27552     75/jump-if-not-equal $mu-branch?:end/disp8
27553     # otherwise return (stmt->operation starts with "return")
27554     (string-starts-with? %ecx "return")  # => eax
27555 $mu-branch?:end:
27556     # . restore registers
27557     59/pop-to-ecx
27558     # . epilogue
27559     89/<- %esp 5/r32/ebp
27560     5d/pop-to-ebp
27561     c3/return
27562 
27563 emit-reverse-break:  # out: (addr buffered-file), stmt: (addr stmt1)
27564     # . prologue
27565     55/push-ebp
27566     89/<- %ebp 4/r32/esp
27567     # . save registers
27568     50/push-eax
27569     # eax = stmt
27570     8b/-> *(ebp+0xc) 0/r32/eax
27571     #
27572     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
27573     (get Reverse-branch %eax 0x10 "reverse-branch: ")  # => eax: (addr handle array byte)
27574     (emit-indent *(ebp+8) *Curr-block-depth)
27575     (lookup *eax *(eax+4))  # => eax
27576     (write-buffered *(ebp+8) %eax)
27577     (write-buffered *(ebp+8) " break/disp32\n")
27578 $emit-reverse-break:end:
27579     # . restore registers
27580     58/pop-to-eax
27581     # . epilogue
27582     89/<- %esp 5/r32/ebp
27583     5d/pop-to-ebp
27584     c3/return
27585 
27586 == data
27587 
27588 # Table from Mu branch instructions to the reverse SubX opcodes for them.
27589 Reverse-branch:  # (table (handle array byte) (handle array byte))
27590   # a table is a stream
27591   0x1c0/imm32/write
27592   0/imm32/read
27593   0x1c0/imm32/size
27594   # data
27595   0x11/imm32/alloc-id   _string-break-if-=/imm32                0x11/imm32/alloc-id   _string_0f_85_jump_label/imm32
27596   0x11/imm32/alloc-id   _string-loop-if-=/imm32                 0x11/imm32/alloc-id   _string_0f_85_jump_label/imm32
27597   0x11/imm32/alloc-id   _string-break-if-!=/imm32               0x11/imm32/alloc-id   _string_0f_84_jump_label/imm32
27598   0x11/imm32/alloc-id   _string-loop-if-!=/imm32                0x11/imm32/alloc-id   _string_0f_84_jump_label/imm32
27599   0x11/imm32/alloc-id   _string-break-if-</imm32                0x11/imm32/alloc-id   _string_0f_8d_jump_label/imm32
27600   0x11/imm32/alloc-id   _string-loop-if-</imm32                 0x11/imm32/alloc-id   _string_0f_8d_jump_label/imm32
27601   0x11/imm32/alloc-id   _string-break-if->/imm32                0x11/imm32/alloc-id   _string_0f_8e_jump_label/imm32
27602   0x11/imm32/alloc-id   _string-loop-if->/imm32                 0x11/imm32/alloc-id   _string_0f_8e_jump_label/imm32
27603   0x11/imm32/alloc-id   _string-break-if-<=/imm32               0x11/imm32/alloc-id   _string_0f_8f_jump_label/imm32
27604   0x11/imm32/alloc-id   _string-loop-if-<=/imm32                0x11/imm32/alloc-id   _string_0f_8f_jump_label/imm32
27605   0x11/imm32/alloc-id   _string-break-if->=/imm32               0x11/imm32/alloc-id   _string_0f_8c_jump_label/imm32
27606   0x11/imm32/alloc-id   _string-loop-if->=/imm32                0x11/imm32/alloc-id   _string_0f_8c_jump_label/imm32
27607   0x11/imm32/alloc-id   _string-break-if-addr</imm32            0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
27608   0x11/imm32/alloc-id   _string-loop-if-addr</imm32             0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
27609   0x11/imm32/alloc-id   _string-break-if-addr>/imm32            0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
27610   0x11/imm32/alloc-id   _string-loop-if-addr>/imm32             0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
27611   0x11/imm32/alloc-id   _string-break-if-addr<=/imm32           0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
27612   0x11/imm32/alloc-id   _string-loop-if-addr<=/imm32            0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
27613   0x11/imm32/alloc-id   _string-break-if-addr>=/imm32           0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
27614   0x11/imm32/alloc-id   _string-loop-if-addr>=/imm32            0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
27615   0x11/imm32/alloc-id   _string-break-if-float</imm32           0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
27616   0x11/imm32/alloc-id   _string-loop-if-float</imm32            0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
27617   0x11/imm32/alloc-id   _string-break-if-float>/imm32           0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
27618   0x11/imm32/alloc-id   _string-loop-if-float>/imm32            0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
27619   0x11/imm32/alloc-id   _string-break-if-float<=/imm32          0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
27620   0x11/imm32/alloc-id   _string-loop-if-float<=/imm32           0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
27621   0x11/imm32/alloc-id   _string-break-if-float>=/imm32          0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
27622   0x11/imm32/alloc-id   _string-loop-if-float>=/imm32           0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
27623 
27624 == code
27625 
27626 emit-unconditional-jump-to-depth:  # out: (addr buffered-file), vars: (addr stack live-var), depth: int, label-suffix: (addr array byte)
27627     # . prologue
27628     55/push-ebp
27629     89/<- %ebp 4/r32/esp
27630     # . save registers
27631     50/push-eax
27632     51/push-ecx
27633     52/push-edx
27634     53/push-ebx
27635     56/push-esi
27636     # ecx = vars
27637     8b/-> *(ebp+0xc) 1/r32/ecx
27638     # var eax: int = vars->top
27639     8b/-> *ecx 0/r32/eax
27640     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
27641     8d/copy-address *(ecx+eax-4) 6/r32/esi  # vars + 8 + vars->top - 12/Live-var-size
27642     # var min/ecx: (addr handle var) = vars->data
27643     8d/copy-address *(ecx+8) 1/r32/ecx
27644     # edx = depth
27645     8b/-> *(ebp+0x10) 2/r32/edx
27646     {
27647 $emit-unconditional-jump-to-depth:loop:
27648       # if (curr < min) break
27649       39/compare %esi 1/r32/ecx
27650       0f 82/jump-if-addr< break/disp32
27651       # var v/ebx: (addr var) = lookup(*curr)
27652       (lookup *esi *(esi+4))  # => eax
27653       89/<- %ebx 0/r32/eax
27654       # if (v->block-depth < until-block-depth) break
27655       39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
27656       0f 8c/jump-if-< break/disp32
27657       {
27658 $emit-unconditional-jump-to-depth:check:
27659         # if v->block-depth != until-block-depth, continue
27660         39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
27661         0f 85/jump-if-!= break/disp32
27662 $emit-unconditional-jump-to-depth:depth-found:
27663         # if v is not a literal, continue
27664         (size-of %ebx)  # => eax
27665         3d/compare-eax-and 0/imm32
27666         0f 85/jump-if-!= break/disp32
27667 $emit-unconditional-jump-to-depth:label-found:
27668         # emit unconditional jump, then return
27669         (emit-indent *(ebp+8) *Curr-block-depth)
27670         (write-buffered *(ebp+8) "e9/jump ")
27671         (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
27672         (write-buffered *(ebp+8) %eax)
27673         (write-buffered *(ebp+8) ":")
27674         (write-buffered *(ebp+8) *(ebp+0x14))
27675         (write-buffered *(ebp+8) "/disp32\n")
27676         eb/jump $emit-unconditional-jump-to-depth:end/disp8
27677       }
27678       # curr -= 12
27679       81 5/subop/subtract %esi 0xc/imm32
27680       e9/jump loop/disp32
27681     }
27682     # TODO: error if no label at 'depth' was found
27683 $emit-unconditional-jump-to-depth:end:
27684     # . restore registers
27685     5e/pop-to-esi
27686     5b/pop-to-ebx
27687     5a/pop-to-edx
27688     59/pop-to-ecx
27689     58/pop-to-eax
27690     # . epilogue
27691     89/<- %esp 5/r32/ebp
27692     5d/pop-to-ebp
27693     c3/return
27694 
27695 # emit clean-up code for 'vars' until some block depth
27696 # doesn't actually modify 'vars' so we need traverse manually inside the stack
27697 emit-cleanup-code-until-depth:  # out: (addr buffered-file), vars: (addr stack live-var), until-block-depth: int
27698     # . prologue
27699     55/push-ebp
27700     89/<- %ebp 4/r32/esp
27701     # . save registers
27702     50/push-eax
27703     51/push-ecx
27704     52/push-edx
27705     53/push-ebx
27706     56/push-esi
27707 #?     (write-buffered Stderr "--- cleanup\n")
27708 #?     (flush Stderr)
27709     # ecx = vars
27710     8b/-> *(ebp+0xc) 1/r32/ecx
27711     # var esi: int = vars->top
27712     8b/-> *ecx 6/r32/esi
27713     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
27714     8d/copy-address *(ecx+esi-4) 6/r32/esi  # vars + 8 + vars->top - 12/Live-var-size
27715     # var min/ecx: (addr handle var) = vars->data
27716     81 0/subop/add %ecx 8/imm32
27717     # edx = until-block-depth
27718     8b/-> *(ebp+0x10) 2/r32/edx
27719     {
27720 $emit-cleanup-code-until-depth:loop:
27721       # if (curr < min) break
27722       39/compare %esi 1/r32/ecx
27723       0f 82/jump-if-addr< break/disp32
27724       # var v/ebx: (addr var) = lookup(*curr)
27725       (lookup *esi *(esi+4))  # => eax
27726       89/<- %ebx 0/r32/eax
27727 #?       (lookup *ebx *(ebx+4))  # Var-name
27728 #?       (write-buffered Stderr "var ")
27729 #?       (write-buffered Stderr %eax)
27730 #?       (write-buffered Stderr Newline)
27731 #?       (flush Stderr)
27732       # if (v->block-depth < until-block-depth) break
27733       39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
27734       0f 8c/jump-if-< break/disp32
27735       # if v is in a register
27736       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
27737       {
27738         0f 84/jump-if-= break/disp32
27739         {
27740 $emit-cleanup-code-until-depth:check-for-previous-spill:
27741           8b/-> *(esi+8) 0/r32/eax  # Live-var-register-spilled
27742           3d/compare-eax-and 0/imm32/false
27743           74/jump-if-= break/disp8
27744 $emit-cleanup-code-until-depth:reclaim-var-in-register:
27745           (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
27746           (emit-pop-register *(ebp+8) %eax)
27747         }
27748         eb/jump $emit-cleanup-code-until-depth:continue/disp8
27749       }
27750       # otherwise v is on the stack
27751       {
27752         75/jump-if-!= break/disp8
27753 $emit-cleanup-code-until-depth:var-on-stack:
27754         (size-of %ebx)  # => eax
27755         # don't emit code for labels
27756         3d/compare-eax-and 0/imm32
27757         74/jump-if-= break/disp8
27758 $emit-cleanup-code-until-depth:reclaim-var-on-stack:
27759         (emit-indent *(ebp+8) *Curr-block-depth)
27760         (write-buffered *(ebp+8) "81 0/subop/add %esp ")
27761         (write-int32-hex-buffered *(ebp+8) %eax)
27762         (write-buffered *(ebp+8) "/imm32\n")
27763       }
27764 $emit-cleanup-code-until-depth:continue:
27765       # curr -= 12
27766       81 5/subop/subtract %esi 0xc/imm32
27767       e9/jump loop/disp32
27768     }
27769 $emit-cleanup-code-until-depth:end:
27770     # . restore registers
27771     5e/pop-to-esi
27772     5b/pop-to-ebx
27773     5a/pop-to-edx
27774     59/pop-to-ecx
27775     58/pop-to-eax
27776     # . epilogue
27777     89/<- %esp 5/r32/ebp
27778     5d/pop-to-ebp
27779     c3/return
27780 
27781 # emit clean-up code for 'vars' that don't conflict with output registers
27782 # doesn't actually modify 'vars' so we need traverse manually inside the stack
27783 emit-cleanup-code-for-non-outputs:  # out: (addr buffered-file), vars: (addr stack live-var), fn: (addr function)
27784     # . prologue
27785     55/push-ebp
27786     89/<- %ebp 4/r32/esp
27787     # . save registers
27788     50/push-eax
27789     51/push-ecx
27790     52/push-edx
27791     53/push-ebx
27792     56/push-esi
27793     57/push-edi
27794     # ecx = vars
27795     8b/-> *(ebp+0xc) 1/r32/ecx
27796     # var esi: int = vars->top
27797     8b/-> *ecx 6/r32/esi
27798     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
27799     8d/copy-address *(ecx+esi-4) 6/r32/esi  # vars + 8 + vars->top - 12/Live-var-size
27800     # var min/ecx: (addr handle var) = vars->data
27801     81 0/subop/add %ecx 8/imm32
27802     {
27803 $emit-cleanup-code-for-non-outputs:loop:
27804       # if (curr < min) break
27805       39/compare %esi 1/r32/ecx
27806       0f 82/jump-if-addr< break/disp32
27807       # var v/ebx: (addr var) = lookup(*curr)
27808       (lookup *esi *(esi+4))  # => eax
27809       89/<- %ebx 0/r32/eax
27810       # if v is in a register
27811       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
27812       {
27813         0f 84/jump-if-= break/disp32
27814         {
27815 $emit-cleanup-code-for-non-outputs:check-for-previous-spill:
27816           8b/-> *(esi+8) 0/r32/eax  # Live-var-register-spilled
27817           3d/compare-eax-and 0/imm32/false
27818           0f 84/jump-if-= break/disp32
27819 $emit-cleanup-code-for-non-outputs:reclaim-var-in-register:
27820           # var reg/edi: (addr array name) = v->register
27821           (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
27822           89/<- %edi 0/r32/eax
27823           # if reg is not in function outputs, emit a pop
27824           (reg-in-function-outputs? *(ebp+0x10) %edi)  # => eax
27825           3d/compare-eax-and 0/imm32/false
27826           {
27827             75/jump-if-!= break/disp8
27828             (emit-pop-register *(ebp+8) %edi)
27829             eb/jump $emit-cleanup-code-for-non-outputs:reclaim-var-in-register-done/disp8
27830           }
27831           # otherwise just drop it from the stack
27832           (emit-indent *(ebp+8) *Curr-block-depth)
27833           (write-buffered *(ebp+8) "81 0/subop/add %esp 4/imm32\n")
27834         }
27835 $emit-cleanup-code-for-non-outputs:reclaim-var-in-register-done:
27836         eb/jump $emit-cleanup-code-for-non-outputs:continue/disp8
27837       }
27838       # otherwise v is on the stack
27839       {
27840         75/jump-if-!= break/disp8
27841 $emit-cleanup-code-for-non-outputs:var-on-stack:
27842         (size-of %ebx)  # => eax
27843         # don't emit code for labels
27844         3d/compare-eax-and 0/imm32
27845         74/jump-if-= break/disp8
27846 $emit-cleanup-code-for-non-outputs:reclaim-var-on-stack:
27847         (emit-indent *(ebp+8) *Curr-block-depth)
27848         (write-buffered *(ebp+8) "81 0/subop/add %esp ")
27849         (write-int32-hex-buffered *(ebp+8) %eax)
27850         (write-buffered *(ebp+8) "/imm32\n")
27851       }
27852 $emit-cleanup-code-for-non-outputs:continue:
27853       # curr -= 12
27854       81 5/subop/subtract %esi 0xc/imm32
27855       e9/jump loop/disp32
27856     }
27857 $emit-cleanup-code-for-non-outputs:end:
27858     # . restore registers
27859     5f/pop-to-edi
27860     5e/pop-to-esi
27861     5b/pop-to-ebx
27862     5a/pop-to-edx
27863     59/pop-to-ecx
27864     58/pop-to-eax
27865     # . epilogue
27866     89/<- %esp 5/r32/ebp
27867     5d/pop-to-ebp
27868     c3/return
27869 
27870 emit-push-register:  # out: (addr buffered-file), reg: (addr array byte)
27871     # . prologue
27872     55/push-ebp
27873     89/<- %ebp 4/r32/esp
27874     # eax = reg
27875     8b/-> *(ebp+0xc) 0/r32/eax
27876     # var prefix/eax: byte = reg->data[0]
27877     8a/copy-byte *(eax+4) 0/r32/AL
27878     81 4/subop/and %eax 0xff/imm32
27879     # if (prefix == 'x') push xmm register
27880     {
27881       3d/compare-eax-and 0x78/imm32/x
27882       0f 85/jump-if-!= break/disp32
27883       # TODO validate register
27884       (emit-indent *(ebp+8) *Curr-block-depth)
27885       (write-buffered *(ebp+8) "81 5/subop/subtract %esp 4/imm32\n")
27886       (emit-indent *(ebp+8) *Curr-block-depth)
27887       (write-buffered *(ebp+8) "f3 0f 11/<- *esp ")
27888       # var prefix/eax: byte = reg->data[3]
27889       8b/-> *(ebp+0xc) 0/r32/eax
27890       8a/copy-byte *(eax+7) 0/r32/AL
27891       81 4/subop/and %eax 0xff/imm32
27892       (write-byte-buffered *(ebp+8) %eax)
27893       (write-buffered *(ebp+8) "/x32\n")
27894       e9/jump $emit-push-register:end/disp32
27895     }
27896     # otherwise push gp register
27897     (emit-indent *(ebp+8) *Curr-block-depth)
27898     (write-buffered *(ebp+8) "ff 6/subop/push %")
27899     (write-buffered *(ebp+8) *(ebp+0xc))
27900     (write-buffered *(ebp+8) Newline)
27901 $emit-push-register:end:
27902     # . epilogue
27903     89/<- %esp 5/r32/ebp
27904     5d/pop-to-ebp
27905     c3/return
27906 
27907 emit-pop-register:  # out: (addr buffered-file), reg: (addr array byte)
27908     # . prologue
27909     55/push-ebp
27910     89/<- %ebp 4/r32/esp
27911     # . save registers
27912     50/push-eax
27913     # eax = reg
27914     8b/-> *(ebp+0xc) 0/r32/eax
27915     # var prefix/eax: byte = reg->data[0]
27916     8a/copy-byte *(eax+4) 0/r32/AL
27917     81 4/subop/and %eax 0xff/imm32
27918     # if (prefix == 'x') pop to xmm register
27919     {
27920       3d/compare-eax-and 0x78/imm32/x
27921       0f 85/jump-if-!= break/disp32
27922       # TODO validate register
27923       (emit-indent *(ebp+8) *Curr-block-depth)
27924       (write-buffered *(ebp+8) "f3 0f 10/-> *esp ")
27925       # var prefix/eax: byte = reg->data[3]
27926       8b/-> *(ebp+0xc) 0/r32/eax
27927       8a/copy-byte *(eax+7) 0/r32/AL
27928       81 4/subop/and %eax 0xff/imm32
27929       (write-byte-buffered *(ebp+8) %eax)
27930       (write-buffered *(ebp+8) "/x32\n")
27931       (emit-indent *(ebp+8) *Curr-block-depth)
27932       (write-buffered *(ebp+8) "81 0/subop/add %esp 4/imm32\n")
27933       e9/jump $emit-pop-register:end/disp32
27934     }
27935     # otherwise pop to gp register
27936     (emit-indent *(ebp+8) *Curr-block-depth)
27937     (write-buffered *(ebp+8) "8f 0/subop/pop %")
27938     (write-buffered *(ebp+8) *(ebp+0xc))
27939     (write-buffered *(ebp+8) Newline)
27940 $emit-pop-register:end:
27941     # . restore registers
27942     58/pop-to-eax
27943     # . epilogue
27944     89/<- %esp 5/r32/ebp
27945     5d/pop-to-ebp
27946     c3/return
27947 
27948 # emit clean-up code for 'vars' until a given label is encountered
27949 # doesn't actually modify 'vars' so we need traverse manually inside the stack
27950 emit-cleanup-code-until-target:  # out: (addr buffered-file), vars: (addr stack live-var), until-block-label: (addr array byte)
27951     # . prologue
27952     55/push-ebp
27953     89/<- %ebp 4/r32/esp
27954     # . save registers
27955     50/push-eax
27956     51/push-ecx
27957     52/push-edx
27958     53/push-ebx
27959     # ecx = vars
27960     8b/-> *(ebp+0xc) 1/r32/ecx
27961     # var eax: int = vars->top
27962     8b/-> *ecx 0/r32/eax
27963     # var curr/edx: (addr handle var) = &vars->data[vars->top - 12]
27964     8d/copy-address *(ecx+eax-4) 2/r32/edx  # vars + 8 + vars->top - 12/Live-var-size
27965     # var min/ecx: (addr handle var) = vars->data
27966     81 0/subop/add %ecx 8/imm32
27967     {
27968 $emit-cleanup-code-until-target:loop:
27969       # if (curr < min) break
27970       39/compare %edx 1/r32/ecx
27971       0f 82/jump-if-addr< break/disp32
27972       # var v/ebx: (handle var) = lookup(*curr)
27973       (lookup *edx *(edx+4))  # => eax
27974       89/<- %ebx 0/r32/eax
27975       # if (v->name == until-block-label) break
27976       (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
27977       (string-equal? %eax *(ebp+0x10))  # => eax
27978       3d/compare-eax-and 0/imm32/false
27979       0f 85/jump-if-!= break/disp32
27980       # if v is in a register
27981       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
27982       {
27983         0f 84/jump-if-= break/disp32
27984         {
27985 $emit-cleanup-code-until-target:check-for-previous-spill:
27986           8b/-> *(edx+8) 0/r32/eax  # Live-var-register-spilled
27987           3d/compare-eax-and 0/imm32/false
27988           74/jump-if-= break/disp8
27989 $emit-cleanup-code-until-target:reclaim-var-in-register:
27990           (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
27991           (emit-pop-register *(ebp+8) %eax)
27992         }
27993         eb/jump $emit-cleanup-code-until-target:continue/disp8
27994       }
27995       # otherwise v is on the stack
27996       {
27997         75/jump-if-!= break/disp8
27998 $emit-cleanup-code-until-target:reclaim-var-on-stack:
27999         (size-of %ebx)  # => eax
28000         # don't emit code for labels
28001         3d/compare-eax-and 0/imm32
28002         74/jump-if-= break/disp8
28003         #
28004         (emit-indent *(ebp+8) *Curr-block-depth)
28005         (write-buffered *(ebp+8) "81 0/subop/add %esp ")
28006         (write-int32-hex-buffered *(ebp+8) %eax)
28007         (write-buffered *(ebp+8) "/imm32\n")
28008       }
28009 $emit-cleanup-code-until-target:continue:
28010       # curr -= 12
28011       81 5/subop/subtract %edx 0xc/imm32
28012       e9/jump loop/disp32
28013     }
28014 $emit-cleanup-code-until-target:end:
28015     # . restore registers
28016     5b/pop-to-ebx
28017     5a/pop-to-edx
28018     59/pop-to-ecx
28019     58/pop-to-eax
28020     # . epilogue
28021     89/<- %esp 5/r32/ebp
28022     5d/pop-to-ebp
28023     c3/return
28024 
28025 # update Curr-local-stack-offset assuming vars until some block depth are popped
28026 # doesn't actually modify 'vars', so we need traverse manually inside the stack
28027 clean-up-stack-offset-state:  # vars: (addr stack live-var), until-block-depth: int
28028     # . prologue
28029     55/push-ebp
28030     89/<- %ebp 4/r32/esp
28031     # . save registers
28032     50/push-eax
28033     51/push-ecx
28034     52/push-edx
28035     53/push-ebx
28036     56/push-esi
28037     # ecx = vars
28038     8b/-> *(ebp+8) 1/r32/ecx
28039     # var esi: int = vars->top
28040     8b/-> *ecx 6/r32/esi
28041     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
28042     8d/copy-address *(ecx+esi-4) 6/r32/esi  # vars + 8 + vars->top - 12/Live-var-size
28043     # var min/ecx: (addr handle var) = vars->data
28044     81 0/subop/add %ecx 8/imm32
28045     # edx = until-block-depth
28046     8b/-> *(ebp+0xc) 2/r32/edx
28047     {
28048 $clean-up-stack-offset-state:loop:
28049       # if (curr < min) break
28050       39/compare %esi 1/r32/ecx
28051       0f 82/jump-if-addr< break/disp32
28052       # var v/ebx: (addr var) = lookup(*curr)
28053       (lookup *esi *(esi+4))  # => eax
28054       89/<- %ebx 0/r32/eax
28055       # if (v->block-depth < until-block-depth) break
28056       39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
28057       0f 8c/jump-if-< break/disp32
28058       # if v is in a register
28059       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
28060       {
28061         0f 84/jump-if-= break/disp32
28062         {
28063 $clean-up-stack-offset-state:check-for-previous-spill:
28064           8b/-> *(esi+8) 0/r32/eax  # Live-var-register-spilled
28065           3d/compare-eax-and 0/imm32/false
28066           74/jump-if-= break/disp8
28067 $clean-up-stack-offset-state:reclaim-var-in-register:
28068           81 0/subop/add *Curr-local-stack-offset 4/imm32
28069         }
28070         eb/jump $clean-up-stack-offset-state:continue/disp8
28071       }
28072       # otherwise v is on the stack
28073       {
28074         75/jump-if-!= break/disp8
28075 $clean-up-stack-offset-state:var-on-stack:
28076         (size-of %ebx)  # => eax
28077         01/add-to *Curr-local-stack-offset 0/r32/eax
28078       }
28079 $clean-up-stack-offset-state:continue:
28080       # curr -= 12
28081       81 5/subop/subtract %esi 0xc/imm32
28082       e9/jump loop/disp32
28083     }
28084 $clean-up-stack-offset-state:end:
28085     # . restore registers
28086     5e/pop-to-esi
28087     5b/pop-to-ebx
28088     5a/pop-to-edx
28089     59/pop-to-ecx
28090     58/pop-to-eax
28091     # . epilogue
28092     89/<- %esp 5/r32/ebp
28093     5d/pop-to-ebp
28094     c3/return
28095 
28096 # Return true if there isn't a variable in 'vars' with the same block-depth
28097 # and register as 'v'.
28098 # 'v' is guaranteed not to be within 'vars'.
28099 not-yet-spilled-this-block?:  # v: (addr var), vars: (addr stack live-var) -> result/eax: boolean
28100     # . prologue
28101     55/push-ebp
28102     89/<- %ebp 4/r32/esp
28103     # . save registers
28104     51/push-ecx
28105     52/push-edx
28106     53/push-ebx
28107     56/push-esi
28108     57/push-edi
28109     # ecx = vars
28110     8b/-> *(ebp+0xc) 1/r32/ecx
28111     # var eax: int = vars->top
28112     8b/-> *ecx 0/r32/eax
28113     # var curr/edx: (addr handle var) = &vars->data[vars->top - 12]
28114     8d/copy-address *(ecx+eax-4) 2/r32/edx  # vars + 8 + vars->top - 12/Live-var-size
28115     # var min/ecx: (addr handle var) = vars->data
28116     8d/copy-address *(ecx+8) 1/r32/ecx
28117     # var depth/ebx: int = v->block-depth
28118     8b/-> *(ebp+8) 3/r32/ebx
28119     8b/-> *(ebx+0x10) 3/r32/ebx  # Var-block-depth
28120     # var needle/esi: (addr array byte) = v->register
28121     8b/-> *(ebp+8) 6/r32/esi
28122     (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
28123     89/<- %esi 0/r32/eax
28124     {
28125 $not-yet-spilled-this-block?:loop:
28126       # if (curr < min) break
28127       39/compare %edx 1/r32/ecx
28128       0f 82/jump-if-addr< break/disp32
28129       # var cand/edi: (addr var) = lookup(*curr)
28130       (lookup *edx *(edx+4))  # => eax
28131       89/<- %edi 0/r32/eax
28132       # if (cand->block-depth < depth) break
28133       39/compare *(edi+0x10) 3/r32/ebx  # Var-block-depth
28134       0f 8c/jump-if-< break/disp32
28135       # var cand-reg/edi: (array array byte) = cand->reg
28136       (lookup *(edi+0x18) *(edi+0x1c))  # Var-register Var-register => eax
28137       89/<- %edi 0/r32/eax
28138       # if (cand-reg == null) continue
28139       {
28140 $not-yet-spilled-this-block?:check-reg:
28141         81 7/subop/compare %edi 0/imm32
28142         0f 84/jump-if-= break/disp32
28143         # if (cand-reg == needle) return true
28144         (string-equal? %esi %edi)  # => eax
28145         3d/compare-eax-and 0/imm32/false
28146         74/jump-if-= break/disp8
28147 $not-yet-spilled-this-block?:return-false:
28148         b8/copy-to-eax 0/imm32/false
28149         eb/jump $not-yet-spilled-this-block?:end/disp8
28150       }
28151 $not-yet-spilled-this-block?:continue:
28152       # curr -= 12
28153       81 5/subop/subtract %edx 0xc/imm32
28154       e9/jump loop/disp32
28155     }
28156 $not-yet-spilled-this-block?:return-true:
28157     # return true
28158     b8/copy-to-eax 1/imm32/true
28159 $not-yet-spilled-this-block?:end:
28160     # . restore registers
28161     5f/pop-to-edi
28162     5e/pop-to-esi
28163     5b/pop-to-ebx
28164     5a/pop-to-edx
28165     59/pop-to-ecx
28166     # . epilogue
28167     89/<- %esp 5/r32/ebp
28168     5d/pop-to-ebp
28169     c3/return
28170 
28171 # could the register of 'v' ever be written to by one of the vars in fn-outputs?
28172 will-not-write-some-register?:  # v: (addr var), stmts: (addr list stmt), fn: (addr function) -> result/eax: boolean
28173     # . prologue
28174     55/push-ebp
28175     89/<- %ebp 4/r32/esp
28176     # eax = v
28177     8b/-> *(ebp+8) 0/r32/eax
28178     # var reg/eax: (addr array byte) = lookup(v->register)
28179     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
28180     # var target/eax: (addr var) = find-register(fn-outputs, reg)
28181     (find-register *(ebp+0x10) %eax)  # => eax
28182     # if (target == 0) return true
28183     {
28184       3d/compare-eax-and 0/imm32
28185       75/jump-if-!= break/disp8
28186       b8/copy-to-eax 1/imm32/true
28187       eb/jump $will-not-write-some-register?:end/disp8
28188     }
28189     # return !assigns-in-stmts?(stmts, target)
28190     (assigns-in-stmts? *(ebp+0xc) %eax)  # => eax
28191     3d/compare-eax-and 0/imm32/false
28192     # assume: true = 1, so no need to mask with 0x000000ff
28193     0f 94/set-if-= %al
28194 $will-not-write-some-register?:end:
28195     # . epilogue
28196     89/<- %esp 5/r32/ebp
28197     5d/pop-to-ebp
28198     c3/return
28199 
28200 # return fn output with matching register
28201 # always returns false if 'reg' is null
28202 find-register:  # fn: (addr function), reg: (addr array byte) -> result/eax: (addr var)
28203     # . prologue
28204     55/push-ebp
28205     89/<- %ebp 4/r32/esp
28206     # . save registers
28207     51/push-ecx
28208     # var curr/ecx: (addr list var) = lookup(fn->outputs)
28209     8b/-> *(ebp+8) 1/r32/ecx
28210     (lookup *(ecx+0x10) *(ecx+0x14))  # Function-outputs Function-outputs => eax
28211     89/<- %ecx 0/r32/eax
28212     {
28213 $find-register:loop:
28214       # if (curr == 0) break
28215       81 7/subop/compare %ecx 0/imm32
28216       74/jump-if-= break/disp8
28217       # eax = curr->value->register
28218       (lookup *ecx *(ecx+4))  # List-value List-value => eax
28219       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
28220       # if (eax == reg) return curr->value
28221 $find-register:compare:
28222       (string-equal? *(ebp+0xc) %eax)  # => eax
28223       {
28224         3d/compare-eax-and 0/imm32/false
28225         74/jump-if-= break/disp8
28226 $find-register:found:
28227         (lookup *ecx *(ecx+4))  # List-value List-value => eax
28228         eb/jump $find-register:end/disp8
28229       }
28230       # curr = lookup(curr->next)
28231       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
28232       89/<- %ecx 0/r32/eax
28233       #
28234       eb/jump loop/disp8
28235     }
28236 $find-register:end:
28237     # . restore registers
28238     59/pop-to-ecx
28239     # . epilogue
28240     89/<- %esp 5/r32/ebp
28241     5d/pop-to-ebp
28242     c3/return
28243 
28244 assigns-in-stmts?:  # stmts: (addr list stmt), v: (addr var) -> result/eax: boolean
28245     # . prologue
28246     55/push-ebp
28247     89/<- %ebp 4/r32/esp
28248     # . save registers
28249     51/push-ecx
28250     # var curr/ecx: (addr list stmt) = stmts
28251     8b/-> *(ebp+8) 1/r32/ecx
28252     {
28253       # if (curr == 0) break
28254       81 7/subop/compare %ecx 0/imm32
28255       74/jump-if-= break/disp8
28256       # if assigns-in-stmt?(curr->value, v) return true
28257       (lookup *ecx *(ecx+4))  # List-value List-value => eax
28258       (assigns-in-stmt? %eax *(ebp+0xc))  # => eax
28259       3d/compare-eax-and 0/imm32/false
28260       75/jump-if-!= break/disp8
28261       # curr = lookup(curr->next)
28262       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
28263       89/<- %ecx 0/r32/eax
28264       #
28265       eb/jump loop/disp8
28266     }
28267 $assigns-in-stmts?:end:
28268     # . restore registers
28269     59/pop-to-ecx
28270     # . epilogue
28271     89/<- %esp 5/r32/ebp
28272     5d/pop-to-ebp
28273     c3/return
28274 
28275 assigns-in-stmt?:  # stmt: (addr stmt), v: (addr var) -> result/eax: boolean
28276     # . prologue
28277     55/push-ebp
28278     89/<- %ebp 4/r32/esp
28279     # . save registers
28280     51/push-ecx
28281     # ecx = stmt
28282     8b/-> *(ebp+8) 1/r32/ecx
28283     # if stmt is a stmt1, return assigns-in-stmt-vars?(stmt->outputs, v)
28284     {
28285       81 7/subop/compare *ecx 1/imm32/stmt1  # Stmt-tag
28286       75/jump-if-!= break/disp8
28287       (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
28288       (assigns-in-stmt-vars? %eax *(ebp+0xc))  # => eax
28289       eb/jump $assigns-in-stmt?:end/disp8
28290     }
28291     # if stmt is a block, return assigns-in-stmts?(stmt->stmts, v)
28292     {
28293       81 7/subop/compare *ecx 0/imm32/block  # Stmt-tag
28294       75/jump-if-!= break/disp8
28295       (lookup *(ecx+4) *(ecx+8))  # Block-stmts Block-stmts => eax
28296       (assigns-in-stmts? %eax *(ebp+0xc))  # => eax
28297       eb/jump $assigns-in-stmt?:end/disp8
28298     }
28299     # otherwise return false
28300     b8/copy 0/imm32/false
28301 $assigns-in-stmt?:end:
28302     # . restore registers
28303     59/pop-to-ecx
28304     # . epilogue
28305     89/<- %esp 5/r32/ebp
28306     5d/pop-to-ebp
28307     c3/return
28308 
28309 assigns-in-stmt-vars?:  # stmt-var: (addr stmt-var), v: (addr var) -> result/eax: boolean
28310     # . prologue
28311     55/push-ebp
28312     89/<- %ebp 4/r32/esp
28313     # . save registers
28314     51/push-ecx
28315     # var curr/ecx: (addr stmt-var) = stmt-var
28316     8b/-> *(ebp+8) 1/r32/ecx
28317     {
28318       # if (curr == 0) break
28319       81 7/subop/compare %ecx 0/imm32
28320       74/jump-if-= break/disp8
28321       # eax = lookup(curr->value)
28322       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
28323       # if (eax == v  &&  curr->is-deref? == false) return true
28324       {
28325         39/compare *(ebp+0xc) 0/r32/eax
28326         75/jump-if-!= break/disp8
28327         81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
28328         75/jump-if-!= break/disp8
28329         b8/copy-to-eax 1/imm32/true
28330         eb/jump $assigns-in-stmt-vars?:end/disp8
28331       }
28332       # curr = lookup(curr->next)
28333       (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
28334       89/<- %ecx 0/r32/eax
28335       #
28336       eb/jump loop/disp8
28337     }
28338 $assigns-in-stmt-vars?:end:
28339     # . restore registers
28340     59/pop-to-ecx
28341     # . epilogue
28342     89/<- %esp 5/r32/ebp
28343     5d/pop-to-ebp
28344     c3/return
28345 
28346 # is there a var before 'v' with the same block-depth and register on the 'vars' stack?
28347 # v is guaranteed to be within vars
28348 # 'start' is provided as an optimization, a pointer within vars
28349 # *start == v
28350 same-register-spilled-before?:  # v: (addr var), vars: (addr stack (handle var)), start: (addr var) -> result/eax: boolean
28351     # . prologue
28352     55/push-ebp
28353     89/<- %ebp 4/r32/esp
28354     # . save registers
28355     51/push-ecx
28356     52/push-edx
28357     53/push-ebx
28358     56/push-esi
28359     57/push-edi
28360     # ecx = v
28361     8b/-> *(ebp+8) 1/r32/ecx
28362     # var reg/edx: (addr array byte) = lookup(v->register)
28363     (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
28364     89/<- %edx 0/r32/eax
28365     # var depth/ebx: int = v->block-depth
28366     8b/-> *(ecx+0x10) 3/r32/ebx  # Var-block-depth
28367     # var min/ecx: (addr handle var) = vars->data
28368     8b/-> *(ebp+0xc) 1/r32/ecx
28369     81 0/subop/add %ecx 8/imm32
28370     # TODO: check that start >= min and start < &vars->data[top]
28371     # TODO: check that *start == v
28372     # var curr/esi: (addr handle var) = start
28373     8b/-> *(ebp+0x10) 6/r32/esi
28374     # curr -= 8
28375     81 5/subop/subtract %esi 8/imm32
28376     {
28377 $same-register-spilled-before?:loop:
28378       # if (curr < min) break
28379       39/compare %esi 1/r32/ecx
28380       0f 82/jump-if-addr< break/disp32
28381       # var x/eax: (addr var) = lookup(*curr)
28382       (lookup *esi *(esi+4))  # => eax
28383       # if (x->block-depth < depth) break
28384       39/compare *(eax+0x10) 3/r32/ebx  # Var-block-depth
28385       0f 8c/jump-if-< break/disp32
28386       # if (x->register == 0) continue
28387       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
28388       74/jump-if-= $same-register-spilled-before?:continue/disp8
28389       # if (x->register == reg) return true
28390       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
28391       (string-equal? %eax %edx)  # => eax
28392       3d/compare-eax-and 0/imm32/false
28393       b8/copy-to-eax 1/imm32/true
28394       75/jump-if-!= $same-register-spilled-before?:end/disp8
28395 $same-register-spilled-before?:continue:
28396       # curr -= 8
28397       81 5/subop/subtract %esi 8/imm32
28398       e9/jump loop/disp32
28399     }
28400 $same-register-spilled-before?:false:
28401     b8/copy-to-eax 0/imm32/false
28402 $same-register-spilled-before?:end:
28403     # . restore registers
28404     5f/pop-to-edi
28405     5e/pop-to-esi
28406     5b/pop-to-ebx
28407     5a/pop-to-edx
28408     59/pop-to-ecx
28409     # . epilogue
28410     89/<- %esp 5/r32/ebp
28411     5d/pop-to-ebp
28412     c3/return
28413 
28414 # clean up global state for 'vars' until some block depth (inclusive)
28415 clean-up-blocks:  # vars: (addr stack live-var), until-block-depth: int, fn: (addr function)
28416     # . prologue
28417     55/push-ebp
28418     89/<- %ebp 4/r32/esp
28419     # . save registers
28420     50/push-eax
28421     51/push-ecx
28422     56/push-esi
28423     # esi = vars
28424     8b/-> *(ebp+8) 6/r32/esi
28425     # ecx = until-block-depth
28426     8b/-> *(ebp+0xc) 1/r32/ecx
28427     {
28428 $clean-up-blocks:reclaim-loop:
28429       # if (vars->top <= 0) break
28430       8b/-> *esi 0/r32/eax  # Stack-top
28431       3d/compare-eax-and 0/imm32
28432       0f 8e/jump-if-<= break/disp32
28433       # var v/eax: (addr var) = lookup(vars[vars->top-12])
28434       (lookup *(esi+eax-4) *(esi+eax))  # vars + 8 + vars->top - 12 => eax
28435       # if (v->block-depth < until-block-depth) break
28436       39/compare *(eax+0x10) 1/r32/ecx  # Var-block-depth
28437       0f 8c/jump-if-< break/disp32
28438       (pop %esi)  # => eax
28439       (pop %esi)  # => eax
28440       (pop %esi)  # => eax
28441       e9/jump loop/disp32
28442     }
28443 $clean-up-blocks:end:
28444     # . restore registers
28445     5e/pop-to-esi
28446     59/pop-to-ecx
28447     58/pop-to-eax
28448     # . epilogue
28449     89/<- %esp 5/r32/ebp
28450     5d/pop-to-ebp
28451     c3/return
28452 
28453 reg-in-function-outputs?:  # fn: (addr function), target: (addr array byte) -> result/eax: boolean
28454     # . prologue
28455     55/push-ebp
28456     89/<- %ebp 4/r32/esp
28457     # . save registers
28458     51/push-ecx
28459     # var curr/ecx: (addr list var) = lookup(fn->outputs)
28460     8b/-> *(ebp+8) 0/r32/eax
28461     (lookup *(eax+0x10) *(eax+0x14))  # Function-outputs Function-outputs => eax
28462     89/<- %ecx 0/r32/eax
28463     # while curr != null
28464     {
28465       81 7/subop/compare %ecx 0/imm32
28466       74/jump-if-= break/disp8
28467       # var v/eax: (addr var) = lookup(curr->value)
28468       (lookup *ecx *(ecx+4))  # List-value List-value => eax
28469       # var reg/eax: (addr array byte) = lookup(v->register)
28470       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
28471       # if (reg == target) return true
28472       (string-equal? %eax *(ebp+0xc))  # => eax
28473       3d/compare-eax-and 0/imm32/false
28474       75/jump-if-!= $reg-in-function-outputs?:end/disp8
28475       # curr = curr->next
28476       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
28477       89/<- %ecx 0/r32/eax
28478       #
28479       eb/jump loop/disp8
28480     }
28481     # return false
28482     b8/copy-to-eax 0/imm32
28483 $reg-in-function-outputs?:end:
28484     # . restore registers
28485     59/pop-to-ecx
28486     # . epilogue
28487     89/<- %esp 5/r32/ebp
28488     5d/pop-to-ebp
28489     c3/return
28490 
28491 emit-subx-var-def:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
28492     # . prologue
28493     55/push-ebp
28494     89/<- %ebp 4/r32/esp
28495     # . save registers
28496     50/push-eax
28497     51/push-ecx
28498     52/push-edx
28499     # eax = stmt
28500     8b/-> *(ebp+0xc) 0/r32/eax
28501     # var v/ecx: (addr var)
28502     (lookup *(eax+4) *(eax+8))  # Vardef-var Vardef-var => eax
28503     89/<- %ecx 0/r32/eax
28504     # v->block-depth = *Curr-block-depth
28505     8b/-> *Curr-block-depth 0/r32/eax
28506     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
28507     # var n/edx: int = size-of(stmt->var)
28508     (size-of %ecx)  # => eax
28509     89/<- %edx 0/r32/eax
28510     # *Curr-local-stack-offset -= n
28511     29/subtract-from *Curr-local-stack-offset 2/r32/edx
28512     # v->offset = *Curr-local-stack-offset
28513     8b/-> *Curr-local-stack-offset 0/r32/eax
28514     89/<- *(ecx+0x14) 0/r32/eax  # Var-offset
28515     # if v is an array, do something special to initialize it
28516     {
28517       (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
28518       (mu-array? %eax)  # => eax
28519       3d/compare-eax-and 0/imm32/false
28520       0f 84/jump-if-= break/disp32
28521       # var array-size-without-size/edx: int = n-4
28522       81 5/subop/subtract %edx 4/imm32
28523       #
28524       (emit-array-data-initialization *(ebp+8) %edx)
28525       e9/jump $emit-subx-var-def:end/disp32
28526     }
28527     # another special-case for initializing streams
28528     # a stream is an array with 2 extra pointers
28529     {
28530       (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
28531       (mu-stream? %eax)  # => eax
28532       3d/compare-eax-and 0/imm32/false
28533       0f 84/jump-if-= break/disp32
28534       # var array-size-without-size/edx: int = n-12
28535       81 5/subop/subtract %edx 0xc/imm32
28536       (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
28537       (emit-stream-data-initialization *(ebp+8) %edx %eax *(ebp+0x10) *(ebp+0x14))
28538       # emit read and write pointers
28539       (emit-indent *(ebp+8) *Curr-block-depth)
28540       (write-buffered *(ebp+8) "68/push 0/imm32\n")
28541       (emit-indent *(ebp+8) *Curr-block-depth)
28542       (write-buffered *(ebp+8) "68/push 0/imm32\n")
28543       #
28544       eb/jump $emit-subx-var-def:end/disp8
28545     }
28546     # while n > 0
28547     {
28548       81 7/subop/compare %edx 0/imm32
28549       7e/jump-if-<= break/disp8
28550       (emit-indent *(ebp+8) *Curr-block-depth)
28551       (write-buffered *(ebp+8) "68/push 0/imm32\n")
28552       # n -= 4
28553       81 5/subop/subtract %edx 4/imm32
28554       #
28555       eb/jump loop/disp8
28556     }
28557 $emit-subx-var-def:end:
28558     # . restore registers
28559     5a/pop-to-edx
28560     59/pop-to-ecx
28561     58/pop-to-eax
28562     # . epilogue
28563     89/<- %esp 5/r32/ebp
28564     5d/pop-to-ebp
28565     c3/return
28566 
28567 emit-array-data-initialization:  # out: (addr buffered-file), n: int
28568     # . prologue
28569     55/push-ebp
28570     89/<- %ebp 4/r32/esp
28571     #
28572     (emit-indent *(ebp+8) *Curr-block-depth)
28573     (write-buffered *(ebp+8) "(push-n-zero-bytes ")
28574     (write-int32-hex-buffered *(ebp+8) *(ebp+0xc))
28575     (write-buffered *(ebp+8) ")\n")
28576     (emit-indent *(ebp+8) *Curr-block-depth)
28577     (write-buffered *(ebp+8) "68/push ")
28578     (write-int32-hex-buffered *(ebp+8) *(ebp+0xc))
28579     (write-buffered *(ebp+8) "/imm32\n")
28580 $emit-array-data-initialization:end:
28581     # . epilogue
28582     89/<- %esp 5/r32/ebp
28583     5d/pop-to-ebp
28584     c3/return
28585 
28586 emit-stream-data-initialization:  # out: (addr buffered-file), n: int, type: (addr type-tree), err: (addr buffered-file), ed: (addr exit-descriptor)
28587     # . prologue
28588     55/push-ebp
28589     89/<- %ebp 4/r32/esp
28590     # . save registers
28591     50/push-eax
28592     # Optimization: if it's a stream of bytes, don't initialize.
28593     #
28594     # We often construct large temporary streams on the stack for 'trace'
28595     # statements. Initializing such streams can significantly slow programs
28596     # down.
28597     #
28598     # Mu doesn't really depend on initializing stream contents for type- or
28599     # memory-safety; we're mostly doing so to make it easy to debug unsafe
28600     # SubX code that misuses stream objects by manipulating read/write
28601     # pointers. But you can't _really_ protect from unsafe SubX, so I think we
28602     # don't give up much safety or security here.
28603     {
28604       (stream-element-type-id *(ebp+0x10) *(ebp+0x14) *(ebp+0x18))  # => eax
28605       3d/compare-eax-and 8/imm32/byte
28606       75/jump-if-!= break/disp8
28607       (emit-indent *(ebp+8) *Curr-block-depth)
28608       (write-buffered *(ebp+8) "81 5/subop/subtract %esp ")
28609       (write-int32-hex-buffered *(ebp+8) *(ebp+0xc))
28610       (write-buffered *(ebp+8) "/imm32\n")
28611       eb/jump $emit-stream-data-initialization:emit-length/disp8
28612     }
28613     (emit-indent *(ebp+8) *Curr-block-depth)
28614     (write-buffered *(ebp+8) "(push-n-zero-bytes ")
28615     (write-int32-hex-buffered *(ebp+8) *(ebp+0xc))
28616     (write-buffered *(ebp+8) ")\n")
28617 $emit-stream-data-initialization:emit-length:
28618     (emit-indent *(ebp+8) *Curr-block-depth)
28619     (write-buffered *(ebp+8) "68/push ")
28620     (write-int32-hex-buffered *(ebp+8) *(ebp+0xc))
28621     (write-buffered *(ebp+8) "/imm32\n")
28622 $emit-stream-data-initialization:end:
28623     # . restore registers
28624     58/pop-to-eax
28625     # . epilogue
28626     89/<- %esp 5/r32/ebp
28627     5d/pop-to-ebp
28628     c3/return
28629 
28630 emit-subx-stmt:  # out: (addr buffered-file), stmt: (addr stmt), primitives: (addr primitive), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
28631     # . prologue
28632     55/push-ebp
28633     89/<- %ebp 4/r32/esp
28634     # . save registers
28635     50/push-eax
28636     51/push-ecx
28637     # - some special-case primitives that don't actually use the 'primitives' data structure
28638     # var op/ecx: (addr array byte) = lookup(stmt->operation)
28639     8b/-> *(ebp+0xc) 1/r32/ecx
28640     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
28641     89/<- %ecx 0/r32/eax
28642     # copy byte (can be a primitive except we need to emit a second instruction)
28643     {
28644       # if (!string-equal?(stmt->operation, "copy-byte")) break
28645       (string-equal? %ecx "copy-byte")  # => eax
28646       3d/compare-eax-and 0/imm32/false
28647       0f 84/jump-if-= break/disp32
28648       (translate-mu-copy-byte-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
28649       e9/jump $emit-subx-stmt:end/disp32
28650     }
28651     # copy-byte-to can be a primitive; writes to memory don't need to clear surrounding bytes
28652     # array size
28653     {
28654       # if (!string-equal?(stmt->operation, "length")) break
28655       (string-equal? %ecx "length")  # => eax
28656       3d/compare-eax-and 0/imm32/false
28657       0f 84/jump-if-= break/disp32
28658       (translate-mu-length-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
28659       e9/jump $emit-subx-stmt:end/disp32
28660     }
28661     # index into array
28662     {
28663       # if (!string-equal?(stmt->operation, "index")) break
28664       (string-equal? %ecx "index")  # => eax
28665       3d/compare-eax-and 0/imm32/false
28666       0f 84/jump-if-= break/disp32
28667       (translate-mu-index-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
28668       e9/jump $emit-subx-stmt:end/disp32
28669     }
28670     # compute-offset for index into array
28671     {
28672       # if (!string-equal?(stmt->operation, "compute-offset")) break
28673       (string-equal? %ecx "compute-offset")  # => eax
28674       3d/compare-eax-and 0/imm32/false
28675       0f 84/jump-if-= break/disp32
28676       (translate-mu-compute-index-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
28677       e9/jump $emit-subx-stmt:end/disp32
28678     }
28679     # get field from record
28680     {
28681       # if (!string-equal?(stmt->operation, "get")) break
28682       (string-equal? %ecx "get")  # => eax
28683       3d/compare-eax-and 0/imm32/false
28684       0f 84/jump-if-= break/disp32
28685       (translate-mu-get-stmt *(ebp+8) *(ebp+0xc))
28686       e9/jump $emit-subx-stmt:end/disp32
28687     }
28688     # allocate scalar
28689     {
28690       # if (!string-equal?(stmt->operation, "allocate")) break
28691       (string-equal? %ecx "allocate")  # => eax
28692       3d/compare-eax-and 0/imm32/false
28693       0f 84/jump-if-= break/disp32
28694       (translate-mu-allocate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
28695       e9/jump $emit-subx-stmt:end/disp32
28696     }
28697     # copy-object
28698     {
28699       # if (!string-equal?(stmt->operation, "copy-object")) break
28700       (string-equal? %ecx "copy-object")  # => eax
28701       3d/compare-eax-and 0/imm32/false
28702       0f 84/jump-if-= break/disp32
28703       (translate-mu-copy-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
28704       e9/jump $emit-subx-stmt:end/disp32
28705     }
28706     # clear-object
28707     {
28708       # if (!string-equal?(stmt->operation, "clear-object")) break
28709       (string-equal? %ecx "clear-object")  # => eax
28710       3d/compare-eax-and 0/imm32/false
28711       0f 84/jump-if-= break/disp32
28712       (translate-mu-clear-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
28713       e9/jump $emit-subx-stmt:end/disp32
28714     }
28715     # allocate array
28716     {
28717       # if (!string-equal?(stmt->operation, "populate")) break
28718       (string-equal? %ecx "populate")  # => eax
28719       3d/compare-eax-and 0/imm32/false
28720       0f 84/jump-if-= break/disp32
28721       (translate-mu-populate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
28722       e9/jump $emit-subx-stmt:end/disp32
28723     }
28724     # allocate stream
28725     {
28726       # if (!string-equal?(stmt->operation, "populate-stream")) break
28727       (string-equal? %ecx "populate-stream")  # => eax
28728       3d/compare-eax-and 0/imm32/false
28729       0f 84/jump-if-= break/disp32
28730       (translate-mu-populate-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
28731       e9/jump $emit-subx-stmt:end/disp32
28732     }
28733     # read from stream
28734     {
28735       # if (!string-equal?(stmt->operation, "read-from-stream")) break
28736       (string-equal? %ecx "read-from-stream")  # => eax
28737       3d/compare-eax-and 0/imm32/false
28738       0f 84/jump-if-= break/disp32
28739       (translate-mu-read-from-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
28740       e9/jump $emit-subx-stmt:end/disp32
28741     }
28742     # write to stream
28743     {
28744       # if (!string-equal?(stmt->operation, "write-to-stream")) break
28745       (string-equal? %ecx "write-to-stream")  # => eax
28746       3d/compare-eax-and 0/imm32/false
28747       0f 84/jump-if-= break/disp32
28748       (translate-mu-write-to-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
28749       e9/jump $emit-subx-stmt:end/disp32
28750     }
28751     # - optimizations
28752     # if copy instruction has same register in source and destination, emit nothing
28753     (redundant-copy? *(ebp+0xc))  # => eax
28754     3d/compare-eax-and 0/imm32/false
28755     75/jump-if-!= $emit-subx-stmt:end/disp8
28756     # - if stmt matches a primitive, emit it
28757     {
28758 $emit-subx-stmt:check-for-primitive:
28759       # var curr/eax: (addr primitive)
28760       (find-matching-primitive *(ebp+0x10) *(ebp+0xc))  # primitives, stmt => eax
28761       3d/compare-eax-and 0/imm32
28762       74/jump-if-= break/disp8
28763 $emit-subx-stmt:primitive:
28764       (emit-subx-primitive *(ebp+8) *(ebp+0xc) %eax)  # out, stmt, curr
28765       e9/jump $emit-subx-stmt:end/disp32
28766     }
28767     # - otherwise emit a call
28768     # TODO: type-checking
28769 $emit-subx-stmt:call:
28770     (emit-call *(ebp+8) *(ebp+0xc))
28771 $emit-subx-stmt:end:
28772     # . restore registers
28773     59/pop-to-ecx
28774     58/pop-to-eax
28775     # . epilogue
28776     89/<- %esp 5/r32/ebp
28777     5d/pop-to-ebp
28778     c3/return
28779 
28780 redundant-copy?:  # stmt: (addr stmt) -> result/eax: boolean
28781     # . prologue
28782     55/push-ebp
28783     89/<- %ebp 4/r32/esp
28784     # . save registers
28785     56/push-esi
28786     57/push-edi
28787     # esi = stmt
28788     8b/-> *(ebp+8) 6/r32/esi
28789     # if stmt->operation != "copy" return false
28790     (lookup *(esi+4) *(esi+8))  # Stmt1-operation Stmt1-operation => eax
28791     (string-equal? %eax "copy")  # => eax
28792     3d/compare-eax-and 0/imm32/false
28793     0f 84/jump-if-= $redundant-copy?:end/disp32
28794     # var output-reg/edi: (addr stmt-var) = stmt->outputs->value->register
28795     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
28796     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
28797     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
28798     # . if output-reg == null, return false
28799     3d/compare-eax-and 0/imm32
28800     74/jump-if-= $redundant-copy?:end/disp8
28801     89/<- %edi 0/r32/eax
28802     # return (inout->value->register == output->value->register)
28803     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
28804     # . if inout->is-deref return false
28805     81 7/subop/compare *(eax+0x10) 0/imm32/false  # Stmt-var-is-deref
28806     {
28807       74/jump-if-= break/disp8
28808       b8/copy-to-eax 0/imm32/false
28809       e9/jump $redundant-copy?:end/disp32
28810     }
28811     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
28812     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
28813     # . if inout-reg == null, return false
28814     3d/compare-eax-and 0/imm32
28815     74/jump-if-= $redundant-copy?:end/disp8
28816     (string-equal? %eax %edi)  # => eax
28817 $redundant-copy?:end:
28818     # . restore registers
28819     5f/pop-to-edi
28820     5e/pop-to-esi
28821     # . epilogue
28822     89/<- %esp 5/r32/ebp
28823     5d/pop-to-ebp
28824     c3/return
28825 
28826 translate-mu-length-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
28827     # . prologue
28828     55/push-ebp
28829     89/<- %ebp 4/r32/esp
28830     # . save registers
28831     50/push-eax
28832     51/push-ecx
28833     52/push-edx
28834     53/push-ebx
28835     56/push-esi
28836     # esi = stmt
28837     8b/-> *(ebp+0xc) 6/r32/esi
28838     # var base/ebx: (addr var) = stmt->inouts[0]->value
28839     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
28840     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
28841     89/<- %ebx 0/r32/eax
28842     # var elemsize/ecx: int = array-element-size(base)
28843     (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
28844     89/<- %ecx 0/r32/eax
28845     # var outreg/edx: (addr array byte) = stmt->outputs[0]->value->register
28846     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
28847     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
28848     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
28849     89/<- %edx 0/r32/eax
28850     # if elemsize == 1
28851     {
28852       81 7/subop/compare %ecx 1/imm32
28853       75/jump-if-!= break/disp8
28854 $translate-mu-length-stmt:size-1:
28855       (emit-save-size-to *(ebp+8) %ebx %edx)
28856       e9/jump $translate-mu-length-stmt:end/disp32
28857     }
28858     # if elemsize is a power of 2 less than 256
28859     {
28860       (power-of-2? %ecx *(ebp+0x10) *(ebp+0x14))  # => eax
28861       3d/compare-eax-and 0/imm32/false
28862       74/jump-if-= break/disp8
28863       81 7/subop/compare %ecx 0xff/imm32
28864       7f/jump-if-> break/disp8
28865 $translate-mu-length-stmt:size-power-of-2:
28866       (emit-save-size-to *(ebp+8) %ebx %edx)
28867       (emit-divide-by-shift-right *(ebp+8) %edx %ecx)
28868       e9/jump $translate-mu-length-stmt:end/disp32
28869     }
28870     # otherwise, the complex case
28871     # . emit register spills
28872     {
28873 $translate-mu-length-stmt:complex:
28874       (string-equal? %edx "eax")  # => eax
28875       3d/compare-eax-and 0/imm32/false
28876       75/break-if-!= break/disp8
28877       (emit-indent *(ebp+8) *Curr-block-depth)
28878       (write-buffered *(ebp+8) "50/push-eax\n")
28879     }
28880     {
28881       (string-equal? %edx "ecx")  # => eax
28882       3d/compare-eax-and 0/imm32/false
28883       75/break-if-!= break/disp8
28884       (emit-indent *(ebp+8) *Curr-block-depth)
28885       (write-buffered *(ebp+8) "51/push-ecx\n")
28886     }
28887     {
28888       (string-equal? %edx "edx")  # => eax
28889       3d/compare-eax-and 0/imm32/false
28890       75/break-if-!= break/disp8
28891       (emit-indent *(ebp+8) *Curr-block-depth)
28892       (write-buffered *(ebp+8) "52/push-edx\n")
28893     }
28894     # .
28895     (emit-save-size-to *(ebp+8) %ebx "eax")
28896     (emit-indent *(ebp+8) *Curr-block-depth)
28897     (write-buffered *(ebp+8) "31/xor %edx 2/r32/edx\n")
28898     (emit-indent *(ebp+8) *Curr-block-depth)
28899     (write-buffered *(ebp+8) "b9/copy-to-ecx ")
28900     (write-int32-hex-buffered *(ebp+8) %ecx)
28901     (write-buffered *(ebp+8) "/imm32\n")
28902     (emit-indent *(ebp+8) *Curr-block-depth)
28903     (write-buffered *(ebp+8) "f7 7/subop/idiv-eax-edx-by %ecx\n")
28904     {
28905       (string-equal? %edx "eax")  # => eax
28906       3d/compare-eax-and 0/imm32/false
28907       75/break-if-!= break/disp8
28908       (emit-indent *(ebp+8) *Curr-block-depth)
28909       (write-buffered *(ebp+8) "89/<- %")
28910       (write-buffered *(ebp+8) %edx)
28911       (write-buffered *(ebp+8) " 0/r32/eax\n")
28912     }
28913     # . emit register restores
28914     {
28915       (string-equal? %edx "edx")  # => eax
28916       3d/compare-eax-and 0/imm32/false
28917       75/break-if-!= break/disp8
28918       (emit-indent *(ebp+8) *Curr-block-depth)
28919       (write-buffered *(ebp+8) "5a/pop-to-edx\n")
28920     }
28921     {
28922       (string-equal? %edx "ecx")  # => eax
28923       3d/compare-eax-and 0/imm32/false
28924       75/break-if-!= break/disp8
28925       (emit-indent *(ebp+8) *Curr-block-depth)
28926       (write-buffered *(ebp+8) "59/pop-to-ecx\n")
28927     }
28928     {
28929       (string-equal? %edx "eax")  # => eax
28930       3d/compare-eax-and 0/imm32/false
28931       75/break-if-!= break/disp8
28932       (emit-indent *(ebp+8) *Curr-block-depth)
28933       (write-buffered *(ebp+8) "58/pop-to-eax\n")
28934     }
28935 $translate-mu-length-stmt:end:
28936     # . restore registers
28937     5e/pop-to-esi
28938     5b/pop-to-ebx
28939     5a/pop-to-edx
28940     59/pop-to-ecx
28941     58/pop-to-eax
28942     # . epilogue
28943     89/<- %esp 5/r32/ebp
28944     5d/pop-to-ebp
28945     c3/return
28946 
28947 array-element-size:  # arr: (addr var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
28948     # . prologue
28949     55/push-ebp
28950     89/<- %ebp 4/r32/esp
28951     #
28952     (array-element-type-id *(ebp+8) *(ebp+0xc) *(ebp+0x10))  # => eax
28953     (size-of-type-id-as-array-element %eax)  # => eax
28954 $array-element-size:end:
28955     # . epilogue
28956     89/<- %esp 5/r32/ebp
28957     5d/pop-to-ebp
28958     c3/return
28959 
28960 array-element-type-id:  # v: (addr var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: type-id
28961     # precondition: n is positive
28962     # . prologue
28963     55/push-ebp
28964     89/<- %ebp 4/r32/esp
28965     #
28966     8b/-> *(ebp+8) 0/r32/eax
28967     # var t/eax: (addr type-tree)
28968     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
28969     # if t == 0 abort
28970     3d/compare-eax-with 0/imm32
28971     0f 84/jump-if-== $array-element-type-id:error0/disp32
28972     # if t->is-atom? abort
28973     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
28974     0f 85/jump-if-!= $array-element-type-id:error1/disp32
28975     # if (t->left == addr) t = t->right
28976     {
28977       50/push-eax
28978       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
28979       (simple-mu-type? %eax 2)  # addr => eax
28980       3d/compare-eax-with 0/imm32/false
28981       58/pop-to-eax
28982       74/jump-if-= break/disp8
28983 $array-element-type-id:skip-addr:
28984       (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
28985     }
28986     # if t == 0 abort
28987     3d/compare-eax-with 0/imm32
28988     0f 84/jump-if-= $array-element-type-id:error2/disp32
28989     # if t->is-atom? abort
28990     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
28991     0f 85/jump-if-!= $array-element-type-id:error2/disp32
28992     # if t->left != array abort
28993     {
28994       50/push-eax
28995       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
28996       (simple-mu-type? %eax 3)  # array => eax
28997       3d/compare-eax-with 0/imm32/false
28998       58/pop-to-eax
28999 $array-element-type-id:no-array:
29000       0f 84/jump-if-= $array-element-type-id:error2/disp32
29001     }
29002 $array-element-type-id:skip-array:
29003     # t = t->right
29004     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
29005     # if t == 0 abort
29006     3d/compare-eax-with 0/imm32
29007     0f 84/jump-if-= $array-element-type-id:error2/disp32
29008     # if t->is-atom? abort
29009     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
29010     0f 85/jump-if-!= $array-element-type-id:error2/disp32
29011     # t = t->left
29012     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
29013     # if (!t->is-atom?) t = t->left     # TODO: assumes array element size can be determined from just first word of array element type
29014     # if (t->is-atom == false) t = lookup(t->left)
29015     {
29016       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
29017       75/jump-if-!= break/disp8
29018       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
29019     }
29020     # return t->value
29021     8b/-> *(eax+4) 0/r32/eax  # Type-tree-value
29022 $array-element-type-id:end:
29023     # . epilogue
29024     89/<- %esp 5/r32/ebp
29025     5d/pop-to-ebp
29026     c3/return
29027 
29028 $array-element-type-id:error0:
29029     (write-buffered *(ebp+0xc) "array-element-type-id: var '")
29030     50/push-eax
29031     8b/-> *(ebp+8) 0/r32/eax
29032     (lookup *eax *(eax+4))  # Var-name Var-name => eax
29033     (write-buffered *(ebp+0xc) %eax)
29034     58/pop-to-eax
29035     (write-buffered *(ebp+0xc) "' has no type\n")
29036     (flush *(ebp+0xc))
29037     (stop *(ebp+0x10) 1)
29038     # never gets here
29039 
29040 $array-element-type-id:error1:
29041     (write-buffered *(ebp+0xc) "array-element-type-id: var '")
29042     50/push-eax
29043     8b/-> *(ebp+8) 0/r32/eax
29044     (lookup *eax *(eax+4))  # Var-name Var-name => eax
29045     (write-buffered *(ebp+0xc) %eax)
29046     58/pop-to-eax
29047     (write-buffered *(ebp+0xc) "' has atomic type ")
29048     (write-int32-hex-buffered *(ebp+0xc) *(eax+4))  # Type-tree-value
29049     (write-buffered *(ebp+0xc) Newline)
29050     (flush *(ebp+0xc))
29051     (stop *(ebp+0x10) 1)
29052     # never gets here
29053 
29054 $array-element-type-id:error2:
29055     (write-buffered *(ebp+0xc) "array-element-type-id: var '")
29056     50/push-eax
29057     8b/-> *(ebp+8) 0/r32/eax
29058     (lookup *eax *(eax+4))  # Var-name Var-name => eax
29059     (write-buffered *(ebp+0xc) %eax)
29060     58/pop-to-eax
29061     (write-buffered *(ebp+0xc) "' has non-array type\n")
29062     (flush *(ebp+0xc))
29063     (stop *(ebp+0x10) 1)
29064     # never gets here
29065 
29066 size-of-type-id-as-array-element:  # t: type-id -> result/eax: int
29067     # . prologue
29068     55/push-ebp
29069     89/<- %ebp 4/r32/esp
29070     # eax = t
29071     8b/-> *(ebp+8) 0/r32/eax
29072     # if t is 'byte', size is 1
29073     3d/compare-eax-and 8/imm32/byte
29074     {
29075       75/jump-if-!= break/disp8
29076       b8/copy-to-eax 1/imm32
29077       eb/jump $size-of-type-id-as-array-element:end/disp8
29078     }
29079     # otherwise proceed as usual
29080     (size-of-type-id %eax)  # => eax
29081 $size-of-type-id-as-array-element:end:
29082     # . epilogue
29083     89/<- %esp 5/r32/ebp
29084     5d/pop-to-ebp
29085     c3/return
29086 
29087 stream-element-type-id:  # type: (addr type-tree), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: type-id
29088     # precondition: n is positive
29089     # . prologue
29090     55/push-ebp
29091     89/<- %ebp 4/r32/esp
29092     # eax = type
29093     8b/-> *(ebp+8) 0/r32/eax
29094     # if type == 0 abort
29095     3d/compare-eax-with 0/imm32
29096     0f 84/jump-if-== $stream-element-type-id:error0/disp32
29097     # if type->is-atom? abort
29098     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
29099     0f 85/jump-if-!= $stream-element-type-id:error1/disp32
29100     # if (type->left == addr) type = type->right
29101     {
29102       50/push-eax
29103       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
29104       (simple-mu-type? %eax 2)  # addr => eax
29105       3d/compare-eax-with 0/imm32/false
29106       58/pop-to-eax
29107       74/jump-if-= break/disp8
29108 $stream-element-type-id:skip-addr:
29109       (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
29110     }
29111     # if type == 0 abort
29112     3d/compare-eax-with 0/imm32
29113     0f 84/jump-if-= $stream-element-type-id:error2/disp32
29114     # if type->is-atom? abort
29115     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
29116     0f 85/jump-if-!= $stream-element-type-id:error2/disp32
29117     # if type->left != stream abort
29118     {
29119       50/push-eax
29120       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
29121       (simple-mu-type? %eax 0xb)  # stream => eax
29122       3d/compare-eax-with 0/imm32/false
29123       58/pop-to-eax
29124 $stream-element-type-id:no-stream:
29125       0f 84/jump-if-= $stream-element-type-id:error2/disp32
29126     }
29127 $stream-element-type-id:skip-stream:
29128     # type = type->right
29129     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
29130     # if type == 0 abort
29131     3d/compare-eax-with 0/imm32
29132     0f 84/jump-if-= $stream-element-type-id:error2/disp32
29133     # if type->is-atom? abort
29134     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
29135     0f 85/jump-if-!= $stream-element-type-id:error2/disp32
29136     # t = type->left
29137     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
29138     # if (!type->is-atom?) type = type->left     # TODO: assumes stream element size can be determined from just first word of stream element type
29139     {
29140       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
29141       75/jump-if-!= break/disp8
29142       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
29143     }
29144     # return type->value
29145     8b/-> *(eax+4) 0/r32/eax  # Type-tree-value
29146 $stream-element-type-id:end:
29147     # . epilogue
29148     89/<- %esp 5/r32/ebp
29149     5d/pop-to-ebp
29150     c3/return
29151 
29152 $stream-element-type-id:error0:
29153     (write-buffered *(ebp+0xc) "stream-element-type-id: var '")
29154     50/push-eax
29155     8b/-> *(ebp+8) 0/r32/eax
29156     (lookup *eax *(eax+4))  # Var-name Var-name => eax
29157     (write-buffered *(ebp+0xc) %eax)
29158     58/pop-to-eax
29159     (write-buffered *(ebp+0xc) "' has no type\n")
29160     (flush *(ebp+0xc))
29161     (stop *(ebp+0x10) 1)
29162     # never gets here
29163 
29164 $stream-element-type-id:error1:
29165     (write-buffered *(ebp+0xc) "stream-element-type-id: var '")
29166     50/push-eax
29167     8b/-> *(ebp+8) 0/r32/eax
29168     (lookup *eax *(eax+4))  # Var-name Var-name => eax
29169     (write-buffered *(ebp+0xc) %eax)
29170     58/pop-to-eax
29171     (write-buffered *(ebp+0xc) "' has atomic type ")
29172     (write-int32-hex-buffered *(ebp+0xc) *(eax+4))  # Type-tree-value
29173     (write-buffered *(ebp+0xc) Newline)
29174     (flush *(ebp+0xc))
29175     (stop *(ebp+0x10) 1)
29176     # never gets here
29177 
29178 $stream-element-type-id:error2:
29179     (write-buffered *(ebp+0xc) "stream-element-type-id: var '")
29180     50/push-eax
29181     8b/-> *(ebp+8) 0/r32/eax
29182     (lookup *eax *(eax+4))  # Var-name Var-name => eax
29183     (write-buffered *(ebp+0xc) %eax)
29184     58/pop-to-eax
29185     (write-buffered *(ebp+0xc) "' has non-stream type\n")
29186     (flush *(ebp+0xc))
29187     (stop *(ebp+0x10) 1)
29188     # never gets here
29189 
29190 emit-save-size-to:  # out: (addr buffered-file), base: (addr var), outreg: (addr array byte)
29191     # . prologue
29192     55/push-ebp
29193     89/<- %ebp 4/r32/esp
29194     # . save registers
29195     50/push-eax
29196     53/push-ebx
29197     # ebx = base
29198     8b/-> *(ebp+0xc) 3/r32/ebx
29199     (emit-indent *(ebp+8) *Curr-block-depth)
29200     (write-buffered *(ebp+8) "8b/-> *")
29201     # if base is an (addr array ...) in a register
29202     {
29203       81 7/subop/compare *(ebx+0x18)) 0/imm32  # Var-register
29204       74/jump-if-= break/disp8
29205 $emit-save-size-to:emit-base-from-register:
29206       (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
29207       (write-buffered *(ebp+8) %eax)
29208       eb/jump $emit-save-size-to:emit-output/disp8
29209     }
29210     # otherwise if base is an (array ...) on the stack
29211     {
29212       81 7/subop/compare *(ebx+0x14)) 0/imm32  # Var-offset
29213       74/jump-if-= break/disp8
29214 $emit-save-size-to:emit-base-from-stack:
29215       (write-buffered *(ebp+8) "(ebp+")
29216       (write-int32-hex-buffered *(ebp+8) *(ebx+0x14))  # Var-offset
29217       (write-buffered *(ebp+8) ")")
29218     }
29219 $emit-save-size-to:emit-output:
29220     (write-buffered *(ebp+8) " ")
29221     (get Mu-registers *(ebp+0x10) 0xc "Mu-registers")  # => eax
29222     (write-int32-hex-buffered *(ebp+8) *eax)
29223     (write-buffered *(ebp+8) "/r32\n")
29224 $emit-save-size-to:end:
29225     # . restore registers
29226     5b/pop-to-ebx
29227     58/pop-to-eax
29228     # . epilogue
29229     89/<- %esp 5/r32/ebp
29230     5d/pop-to-ebp
29231     c3/return
29232 
29233 emit-divide-by-shift-right:  # out: (addr buffered-file), reg: (addr array byte), size: int
29234     # . prologue
29235     55/push-ebp
29236     89/<- %ebp 4/r32/esp
29237     # . save registers
29238     50/push-eax
29239     #
29240     (emit-indent *(ebp+8) *Curr-block-depth)
29241     (write-buffered *(ebp+8) "c1/shift 5/subop/>> %")
29242     (write-buffered *(ebp+8) *(ebp+0xc))
29243     (write-buffered *(ebp+8) Space)
29244     (num-shift-rights *(ebp+0x10))  # => eax
29245     (write-int32-hex-buffered *(ebp+8) %eax)
29246     (write-buffered *(ebp+8) "/imm8\n")
29247 $emit-divide-by-shift-right:end:
29248     # . restore registers
29249     58/pop-to-eax
29250     # . epilogue
29251     89/<- %esp 5/r32/ebp
29252     5d/pop-to-ebp
29253     c3/return
29254 
29255 translate-mu-copy-byte-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
29256     # . prologue
29257     55/push-ebp
29258     89/<- %ebp 4/r32/esp
29259     # . save registers
29260     50/push-eax
29261     56/push-esi
29262     # esi = stmt
29263     8b/-> *(ebp+0xc) 6/r32/esi
29264     #
29265     (emit-indent *(ebp+8) *Curr-block-depth)
29266     (write-buffered *(ebp+8) "8a/byte->")
29267     # emit stmt->inouts[0]
29268     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29269     (emit-subx-var-as-rm32 *(ebp+8) %eax)
29270     # emit /r32 for stmt->outputs[0]->register
29271     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
29272     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29273     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
29274     (maybe-get Mu-registers %eax 0xc)  # => eax: (addr register-index)
29275     (write-buffered *(ebp+8) Space)
29276     (write-int32-hex-buffered *(ebp+8) *eax)
29277     (write-buffered *(ebp+8) "/r32\n")
29278     # clear rest of register
29279     (emit-indent *(ebp+8) *Curr-block-depth)
29280     (write-buffered *(ebp+8) "81 4/subop/and %")
29281     8b/-> *(ebp+0xc) 0/r32/eax
29282     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
29283     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29284     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
29285     (write-buffered *(ebp+8) %eax)
29286     (write-buffered *(ebp+8) " 0xff/imm32\n")
29287 $translate-mu-copy-byte-stmt:end:
29288     # . restore registers
29289     5e/pop-to-esi
29290     58/pop-to-eax
29291     # . epilogue
29292     89/<- %esp 5/r32/ebp
29293     5d/pop-to-ebp
29294     c3/return
29295 
29296 # a little different from other translate- functions; notice the extra 'fn' argument
29297 translate-mu-index-stmt:  # out: (addr buffered-file), stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
29298     # . prologue
29299     55/push-ebp
29300     89/<- %ebp 4/r32/esp
29301     # . save registers
29302     53/push-ebx
29303     # ebx = stmt
29304     8b/-> *(ebp+0xc) 3/r32/ebx
29305     # var base/ebx: (addr var) = stmt->inouts[0]
29306     (lookup *(ebx+0xc) *(ebx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29307     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29308     89/<- %ebx 0/r32/eax
29309     # emit bounds-check
29310     (emit-mu-index-bounds-check *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18))
29311     # if (var->register) do one thing
29312     {
29313       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
29314       74/jump-if-= break/disp8
29315       # TODO: ensure there's no dereference
29316       (translate-mu-index-stmt-with-array-in-register *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
29317       eb/jump $translate-mu-index-stmt:end/disp8
29318     }
29319     # if (var->offset) do a different thing
29320     {
29321       81 7/subop/compare *(ebx+0x14) 0/imm32  # Var-offset
29322       74/jump-if-= break/disp8
29323       # TODO: ensure there's no dereference
29324       (translate-mu-index-stmt-with-array-on-stack *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
29325       eb/jump $translate-mu-index-stmt:end/disp8
29326     }
29327 $translate-mu-index-stmt:end:
29328     # . restore registers
29329     5b/pop-to-ebx
29330     # . epilogue
29331     89/<- %esp 5/r32/ebp
29332     5d/pop-to-ebp
29333     c3/return
29334 
29335 $translate-mu-index-stmt:error1:
29336     (write-buffered *(ebp+0x14) "couldn't translate an index instruction. second (index) input must either lie in a register or be a literal\n")
29337     (flush *(ebp+0x14))
29338     (stop *(ebp+0x18) 1)
29339     # never gets here
29340 
29341 $translate-mu-index-stmt:error2:
29342     (write-buffered *(ebp+0x14) "couldn't translate an index instruction. second (index) input when in a register must be an int or offset\n")
29343     (flush *(ebp+0x14))
29344     (stop *(ebp+0x18) 1)
29345     # never gets here
29346 
29347 emit-mu-index-bounds-check:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
29348     # . prologue
29349     55/push-ebp
29350     89/<- %ebp 4/r32/esp
29351     # . save registers
29352     50/push-eax
29353     51/push-ecx
29354     52/push-edx
29355     53/push-ebx
29356     # ecx = stmt
29357     8b/-> *(ebp+0xc) 1/r32/ecx
29358     #
29359     (emit-indent *(ebp+8) *Curr-block-depth)
29360     (write-buffered *(ebp+8) "(__check-mu-array-bounds ")
29361 $emit-mu-index-bounds-check:compute-base:
29362     # var base/ebx: (addr var) = inouts[0]
29363     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29364     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29365     89/<- %ebx 0/r32/eax
29366 $emit-mu-index-bounds-check:emit-index:
29367     # var index/edx: (addr var) = inouts[1]
29368     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29369     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
29370     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29371     89/<- %edx 0/r32/eax
29372     # if index->register, print its code
29373     81 7/subop/compare *(edx+0x18) 0/imm32  # Var-register
29374     {
29375       0f 84/jump-if-= break/disp32
29376 $emit-mu-index-bounds-check:emit-register-index:
29377       (write-buffered *(ebp+8) "%")
29378       (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
29379       (write-buffered *(ebp+8) %eax)
29380       eb/jump $emit-mu-index-bounds-check:index-done/disp8
29381     }
29382     # otherwise if index is a literal, print it
29383 $emit-mu-index-bounds-check:emit-literal-index:
29384     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
29385     (simple-mu-type? %eax 0)  # => eax
29386     3d/compare-eax-and 0/imm32/false
29387     {
29388       0f 84/jump-if-= break/disp32
29389       (lookup *edx *(edx+4))  # Var-name Var-name => eax
29390       (write-buffered *(ebp+8) %eax)
29391     }
29392 $emit-mu-index-bounds-check:index-done:
29393     (write-buffered *(ebp+8) " ")
29394 $emit-mu-index-bounds-check:emit-element-size:
29395     # if index is a literal or int, print size of array element
29396     {
29397       {
29398         (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
29399         (simple-mu-type? %eax 0)  # literal => eax
29400         3d/compare-eax-and 0/imm32/false
29401         75/jump-if-!= break/disp8
29402         (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
29403         (simple-mu-type? %eax 1)  # int => eax
29404         3d/compare-eax-and 0/imm32/false
29405         75/jump-if-!= break/disp8
29406         eb/jump $emit-mu-index-bounds-check:emit-element-size-offset/disp8
29407       }
29408 $emit-mu-index-bounds-check:emit-int-register-index:
29409       (array-element-size %ebx *(ebp+0x14) *(ebp+0x18))  # => eax
29410       (write-int32-hex-buffered *(ebp+8) %eax)
29411       e9/jump $emit-mu-index-bounds-check:emit-base/disp32
29412     }
29413 $emit-mu-index-bounds-check:emit-element-size-offset:
29414     # if index has type (offset ...), print "1"
29415     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
29416     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
29417     {
29418       75/jump-if-!= break/disp8
29419       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
29420       (simple-mu-type? %eax 7)  # => eax
29421       3d/compare-eax-and 0/imm32/false
29422       {
29423         0f 84/jump-if-= break/disp32
29424 $emit-mu-index-bounds-check:emit-offset-register-index:
29425         (write-buffered *(ebp+8) "1")
29426       }
29427     }
29428 $emit-mu-index-bounds-check:emit-base:
29429     # if base is in a register, print " *" base->register
29430     81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
29431     {
29432       74/jump-if-= break/disp8
29433       (write-buffered *(ebp+8) " *")
29434       (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
29435       (write-buffered *(ebp+8) %eax)
29436       e9/jump $emit-mu-index-bounds-check:emit-function-name/disp32
29437     }
29438     # otherwise print " *(ebp+" base->offset ")"
29439     (write-buffered *(ebp+8) " *(ebp+")
29440     (write-int32-hex-buffered *(ebp+8) *(ebx+0x14))  # Var-offset
29441     (write-buffered *(ebp+8) ")")
29442 $emit-mu-index-bounds-check:emit-function-name:
29443     # " \"" function-name "\""
29444     (write-buffered *(ebp+8) " \"")
29445     8b/-> *(ebp+0x10) 1/r32/ecx
29446     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
29447     (write-buffered *(ebp+8) %eax)
29448     (write-buffered *(ebp+8) "\"")
29449 $emit-mu-index-bounds-check:emit-array-name:
29450     # " \"" base->name "\""
29451     (write-buffered *(ebp+8) " \"")
29452     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
29453     (write-buffered *(ebp+8) %eax)
29454     (write-buffered *(ebp+8) "\")\n")
29455 $emit-mu-index-bounds-check:end:
29456     # . restore registers
29457     5b/pop-to-ebx
29458     5a/pop-to-edx
29459     59/pop-to-ecx
29460     58/pop-to-eax
29461     # . epilogue
29462     89/<- %esp 5/r32/ebp
29463     5d/pop-to-ebp
29464     c3/return
29465 
29466 translate-mu-index-stmt-with-array-in-register:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
29467     # . prologue
29468     55/push-ebp
29469     89/<- %ebp 4/r32/esp
29470     # . save registers
29471     50/push-eax
29472     51/push-ecx
29473     52/push-edx
29474     53/push-ebx
29475     #
29476     (emit-indent *(ebp+8) *Curr-block-depth)
29477     (write-buffered *(ebp+8) "8d/copy-address *(")
29478     # TODO: ensure inouts[0] is in a register and not dereferenced
29479 $translate-mu-index-stmt-with-array-in-register:emit-base:
29480     # ecx = stmt
29481     8b/-> *(ebp+0xc) 1/r32/ecx
29482     # var base/ebx: (addr var) = inouts[0]
29483     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29484     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29485     89/<- %ebx 0/r32/eax
29486     # print base->register " + "
29487     (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
29488     (write-buffered *(ebp+8) %eax)
29489     (write-buffered *(ebp+8) " + ")
29490     # var index/edx: (addr var) = inouts[1]
29491     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29492     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
29493     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29494     89/<- %edx 0/r32/eax
29495     # if index->register
29496     81 7/subop/compare *(edx+0x18) 0/imm32  # Var-register
29497     {
29498       0f 84/jump-if-= break/disp32
29499 $translate-mu-index-stmt-with-array-in-register:emit-register-index:
29500       # if index is an int
29501       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
29502       (simple-mu-type? %eax 1)  # int => eax
29503       3d/compare-eax-and 0/imm32/false
29504       {
29505         0f 84/jump-if-= break/disp32
29506 $translate-mu-index-stmt-with-array-in-register:emit-int-register-index:
29507         # print index->register "<<" log2(array-element-size(base)) " + 4) "
29508         # . index->register "<<"
29509         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
29510         (write-buffered *(ebp+8) %eax)
29511         (write-buffered *(ebp+8) "<<")
29512         # . log2(array-element-size(base->type))
29513         # we know size is a power of 2
29514         (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
29515         (num-shift-rights %eax)  # => eax
29516         (write-int32-hex-buffered *(ebp+8) %eax)
29517         e9/jump $translate-mu-index-stmt-with-array-in-register:emit-register-index-done/disp32
29518       }
29519       # if index->type is any other atom, abort
29520       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
29521       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
29522       0f 85/jump-if-!= $translate-mu-index-stmt:error2/disp32
29523       # if index has type (offset ...)
29524       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
29525       (simple-mu-type? %eax 7)  # => eax
29526       3d/compare-eax-and 0/imm32/false
29527       {
29528         0f 84/jump-if-= break/disp32
29529         # print index->register
29530 $translate-mu-index-stmt-with-array-in-register:emit-offset-register-index:
29531         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
29532         (write-buffered *(ebp+8) %eax)
29533       }
29534 $translate-mu-index-stmt-with-array-in-register:emit-register-index-done:
29535       (write-buffered *(ebp+8) " + 4) ")
29536       e9/jump $translate-mu-index-stmt-with-array-in-register:emit-output/disp32
29537     }
29538     # otherwise if index is a literal
29539     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
29540     (simple-mu-type? %eax 0)  # => eax
29541     3d/compare-eax-and 0/imm32/false
29542     {
29543       0f 84/jump-if-= break/disp32
29544 $translate-mu-index-stmt-with-array-in-register:emit-literal-index:
29545       # var index-value/edx: int = parse-hex-int(index->name)
29546       (lookup *edx *(edx+4))  # Var-name Var-name => eax
29547       (parse-hex-int %eax)  # => eax
29548       89/<- %edx 0/r32/eax
29549       # offset = idx-value * array-element-size(base->type)
29550       (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
29551       f7 4/subop/multiply-into-edx-eax %edx  # clobbers edx
29552       # offset += 4 for array size
29553       05/add-to-eax 4/imm32
29554       # TODO: check edx for overflow
29555       # print offset
29556       (write-int32-hex-buffered *(ebp+8) %eax)
29557       (write-buffered *(ebp+8) ") ")
29558       e9/jump $translate-mu-index-stmt-with-array-in-register:emit-output/disp32
29559     }
29560     # otherwise abort
29561     e9/jump $translate-mu-index-stmt:error1/disp32
29562 $translate-mu-index-stmt-with-array-in-register:emit-output:
29563     # outputs[0] "/r32"
29564     8b/-> *(ebp+0xc) 1/r32/ecx
29565     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
29566     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29567     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
29568     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
29569     (write-int32-hex-buffered *(ebp+8) *eax)
29570     (write-buffered *(ebp+8) "/r32\n")
29571 $translate-mu-index-stmt-with-array-in-register:end:
29572     # . restore registers
29573     5b/pop-to-ebx
29574     5a/pop-to-edx
29575     59/pop-to-ecx
29576     58/pop-to-eax
29577     # . epilogue
29578     89/<- %esp 5/r32/ebp
29579     5d/pop-to-ebp
29580     c3/return
29581 
29582 translate-mu-index-stmt-with-array-on-stack:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
29583     # . prologue
29584     55/push-ebp
29585     89/<- %ebp 4/r32/esp
29586     # . save registers
29587     50/push-eax
29588     51/push-ecx
29589     52/push-edx
29590     53/push-ebx
29591     #
29592     (emit-indent *(ebp+8) *Curr-block-depth)
29593     (write-buffered *(ebp+8) "8d/copy-address *(ebp + ")
29594     # var curr/edx: (addr stmt-var) = lookup(stmt->inouts)
29595     8b/-> *(ebp+0xc) 0/r32/eax
29596     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29597     89/<- %edx 0/r32/eax
29598     # var base/ecx: (addr var) = lookup(curr->value)
29599     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29600     89/<- %ecx 0/r32/eax
29601     # var curr2/eax: (addr stmt-var) = lookup(curr->next)
29602     (lookup *(edx+8) *(edx+0xc))  # Stmt-var-next Stmt-var-next => eax
29603     # var index/edx: (handle var) = curr2->value
29604     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29605     89/<- %edx 0/r32/eax
29606     # if index->register
29607     81 7/subop/compare *(edx+0x18) 0/imm32  # Var-register
29608     {
29609       0f 84/jump-if-= break/disp32
29610 $translate-mu-index-stmt-with-array-on-stack:emit-register-index:
29611       # if index is an int
29612       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
29613       (simple-mu-type? %eax 1)  # int => eax
29614       3d/compare-eax-and 0/imm32/false
29615       {
29616         0f 84/jump-if-= break/disp32
29617 $translate-mu-index-stmt-with-array-on-stack:emit-int-register-index:
29618         # print index->register "<<" log2(array-element-size(base)) " + " base->offset+4
29619         # . inouts[1]->register "<<"
29620         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
29621         (write-buffered *(ebp+8) %eax)
29622         (write-buffered *(ebp+8) "<<")
29623         # . log2(array-element-size(base))
29624         # TODO: ensure size is a power of 2
29625         (array-element-size %ecx *(ebp+0x10) *(ebp+0x14))  # => eax
29626         (num-shift-rights %eax)  # => eax
29627         (write-int32-hex-buffered *(ebp+8) %eax)
29628         #
29629         (write-buffered *(ebp+8) " + ")
29630         #
29631         8b/-> *(ecx+0x14) 0/r32/eax  # Var-offset
29632         05/add-to-eax 4/imm32  # for array length
29633         (write-int32-hex-buffered *(ebp+8) %eax)
29634         e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-register-index-done/disp32
29635       }
29636       # if index->type is any other atom, abort
29637       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
29638       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
29639       0f 85/jump-if-!= $translate-mu-index-stmt:error2/disp32
29640       # if index has type (offset ...)
29641       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
29642       (simple-mu-type? %eax 7)  # => eax
29643       3d/compare-eax-and 0/imm32/false
29644       {
29645         0f 84/jump-if-= break/disp32
29646         # print index->register
29647 $translate-mu-index-stmt-with-array-on-stack:emit-offset-register-index:
29648         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
29649         (write-buffered *(ebp+8) %eax)
29650       }
29651 $translate-mu-index-stmt-with-array-on-stack:emit-register-index-done:
29652       (write-buffered *(ebp+8) ") ")
29653       e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-output/disp32
29654     }
29655     # otherwise if index is a literal
29656     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
29657     (simple-mu-type? %eax 0)  # => eax
29658     3d/compare-eax-and 0/imm32/false
29659     {
29660       0f 84/jump-if-= break/disp32
29661 $translate-mu-index-stmt-with-array-on-stack:emit-literal-index:
29662       # var idx-value/edx: int = parse-hex-int(index->name)
29663       (lookup *edx *(edx+4))  # Var-name Var-name => eax
29664       (parse-hex-int %eax)  # Var-name => eax
29665       89/<- %edx 0/r32/eax
29666       # offset = idx-value * array-element-size(base)
29667       (array-element-size %ecx *(ebp+0x10) *(ebp+0x14))  # => eax
29668       f7 4/subop/multiply-into-edx-eax %edx  # clobbers edx
29669       # offset += base->offset
29670       03/add *(ecx+0x14) 0/r32/eax  # Var-offset
29671       # offset += 4 for array size
29672       05/add-to-eax 4/imm32
29673       # TODO: check edx for overflow
29674       # print offset
29675       (write-int32-hex-buffered *(ebp+8) %eax)
29676       (write-buffered *(ebp+8) ") ")
29677       e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-output/disp32
29678     }
29679     # otherwise abort
29680     e9/jump $translate-mu-index-stmt:error1/disp32
29681 $translate-mu-index-stmt-with-array-on-stack:emit-output:
29682     # outputs[0] "/r32"
29683     8b/-> *(ebp+0xc) 0/r32/eax
29684     (lookup *(eax+0x14) *(eax+0x18))  # Stmt1-outputs Stmt1-outputs => eax
29685     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29686     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
29687     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
29688     (write-int32-hex-buffered *(ebp+8) *eax)
29689     (write-buffered *(ebp+8) "/r32\n")
29690 $translate-mu-index-stmt-with-array-on-stack:end:
29691     # . restore registers
29692     5b/pop-to-ebx
29693     5a/pop-to-edx
29694     59/pop-to-ecx
29695     58/pop-to-eax
29696     # . epilogue
29697     89/<- %esp 5/r32/ebp
29698     5d/pop-to-ebp
29699     c3/return
29700 
29701 translate-mu-compute-index-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
29702     # . prologue
29703     55/push-ebp
29704     89/<- %ebp 4/r32/esp
29705     # . save registers
29706     50/push-eax
29707     51/push-ecx
29708     52/push-edx
29709     53/push-ebx
29710     #
29711     (emit-indent *(ebp+8) *Curr-block-depth)
29712     (write-buffered *(ebp+8) "69/multiply")
29713     # ecx = stmt
29714     8b/-> *(ebp+0xc) 1/r32/ecx
29715     # var first-inout/ebx: (addr stmt-var) = stmt->inouts[0]
29716     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29717     89/<- %ebx 0/r32/eax
29718 $translate-mu-compute-index-stmt:emit-index:
29719     (lookup *(ebx+8) *(ebx+0xc))  # Stmt-var-next Stmt-var-next => eax
29720     (emit-subx-var-as-rm32 *(ebp+8) %eax)
29721     (write-buffered *(ebp+8) Space)
29722 $translate-mu-compute-index-stmt:emit-elem-size:
29723     # var base/ebx: (addr var)
29724     (lookup *ebx *(ebx+4))  # Stmt-var-value Stmt-var-value => eax
29725     89/<- %ebx 0/r32/eax
29726     # print array-element-size(base)
29727     (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
29728     (write-int32-hex-buffered *(ebp+8) %eax)
29729     (write-buffered *(ebp+8) "/imm32 ")
29730 $translate-mu-compute-index-stmt:emit-output:
29731     # outputs[0] "/r32"
29732     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
29733     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29734     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
29735     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
29736     (write-int32-hex-buffered *(ebp+8) *eax)
29737     (write-buffered *(ebp+8) "/r32\n")
29738 $translate-mu-compute-index-stmt:end:
29739     # . restore registers
29740     5b/pop-to-ebx
29741     5a/pop-to-edx
29742     59/pop-to-ecx
29743     58/pop-to-eax
29744     # . epilogue
29745     89/<- %esp 5/r32/ebp
29746     5d/pop-to-ebp
29747     c3/return
29748 
29749 translate-mu-get-stmt:  # out: (addr buffered-file), stmt: (addr stmt)
29750     # . prologue
29751     55/push-ebp
29752     89/<- %ebp 4/r32/esp
29753     # . save registers
29754     50/push-eax
29755     51/push-ecx
29756     52/push-edx
29757     #
29758     (emit-indent *(ebp+8) *Curr-block-depth)
29759     (write-buffered *(ebp+8) "8d/copy-address ")
29760     # ecx = stmt
29761     8b/-> *(ebp+0xc) 1/r32/ecx
29762     # var offset/edx: int = get offset of stmt
29763     (mu-get-offset %ecx)  # => eax
29764     89/<- %edx 0/r32/eax
29765     # var base/eax: (addr var) = stmt->inouts->value
29766     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29767     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29768     # if base is in a register
29769     81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
29770     {
29771       0f 84/jump-if-= break/disp32
29772 $translate-mu-get-stmt:emit-register-input:
29773       # emit "*(" base->register " + " offset ") "
29774       (write-buffered *(ebp+8) "*(")
29775       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
29776       (write-buffered *(ebp+8) %eax)
29777       (write-buffered *(ebp+8) " + ")
29778       (write-int32-hex-buffered *(ebp+8) %edx)
29779       (write-buffered *(ebp+8) ") ")
29780       e9/jump $translate-mu-get-stmt:emit-output/disp32
29781     }
29782     # otherwise base is on the stack
29783     {
29784 $translate-mu-get-stmt:emit-stack-input:
29785       # emit "*(ebp + " inouts[0]->stack-offset + offset ") "
29786       (write-buffered *(ebp+8) "*(ebp+")
29787       03/add *(eax+0x14) 2/r32/edx  # Var-offset
29788       (write-int32-hex-buffered *(ebp+8) %edx)
29789       (write-buffered *(ebp+8) ") ")
29790       eb/jump $translate-mu-get-stmt:emit-output/disp8
29791     }
29792 $translate-mu-get-stmt:emit-output:
29793     # var output/eax: (addr var) = stmt->outputs->value
29794     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
29795     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29796     # emit offset->register "/r32"
29797     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
29798     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
29799     (write-int32-hex-buffered *(ebp+8) *eax)
29800     (write-buffered *(ebp+8) "/r32\n")
29801 $translate-mu-get-stmt:end:
29802     # . restore registers
29803     5a/pop-to-edx
29804     59/pop-to-ecx
29805     58/pop-to-eax
29806     # . epilogue
29807     89/<- %esp 5/r32/ebp
29808     5d/pop-to-ebp
29809     c3/return
29810 
29811 translate-mu-copy-object-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
29812     # . prologue
29813     55/push-ebp
29814     89/<- %ebp 4/r32/esp
29815     # . save registers
29816     50/push-eax
29817     #
29818     (emit-indent *(ebp+8) *Curr-block-depth)
29819     (write-buffered *(ebp+8) "(copy-bytes")
29820     # eax = stmt
29821     8b/-> *(ebp+0xc) 0/r32/eax
29822     # var first-inout/eax: (addr stmt-var) = stmt->inouts[0]
29823     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29824     (emit-subx-call-operand *(ebp+8) %eax)
29825     # var second-inout/eax: (addr stmt-var) = stmt->inouts[1]
29826     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
29827     (emit-subx-call-operand *(ebp+8) %eax)
29828     # emit size of inouts
29829     (write-buffered *(ebp+8) Space)
29830     (addr-payload-size %eax *(ebp+0x10) *(ebp+0x14))  # => eax
29831     (write-int32-hex-buffered *(ebp+8) %eax)
29832     (write-buffered *(ebp+8) ")\n")
29833 $translate-mu-copy-object-stmt:end:
29834     # . restore registers
29835     58/pop-to-eax
29836     # . epilogue
29837     89/<- %esp 5/r32/ebp
29838     5d/pop-to-ebp
29839     c3/return
29840 
29841 translate-mu-clear-object-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
29842     # . prologue
29843     55/push-ebp
29844     89/<- %ebp 4/r32/esp
29845     # . save registers
29846     50/push-eax
29847     #
29848     (emit-indent *(ebp+8) *Curr-block-depth)
29849     (write-buffered *(ebp+8) "(zero-out")
29850     # eax = stmt
29851     8b/-> *(ebp+0xc) 0/r32/eax
29852     # var dest/eax: (addr stmt-var) = stmt->inouts[0]
29853     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29854     #
29855     (emit-subx-call-operand *(ebp+8) %eax)
29856     (write-buffered *(ebp+8) Space)
29857     (addr-payload-size %eax *(ebp+0x10) *(ebp+0x14))  # => eax
29858     (write-int32-hex-buffered *(ebp+8) %eax)
29859     (write-buffered *(ebp+8) ")\n")
29860 $translate-mu-clear-object-stmt:end:
29861     # . restore registers
29862     58/pop-to-eax
29863     # . epilogue
29864     89/<- %esp 5/r32/ebp
29865     5d/pop-to-ebp
29866     c3/return
29867 
29868 translate-mu-allocate-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
29869     # . prologue
29870     55/push-ebp
29871     89/<- %ebp 4/r32/esp
29872     # . save registers
29873     50/push-eax
29874     56/push-esi
29875     57/push-edi
29876     # esi = stmt
29877     8b/-> *(ebp+0xc) 6/r32/esi
29878     # var target/edi: (addr stmt-var) = stmt->inouts[0]
29879     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29880     89/<- %edi 0/r32/eax
29881     #
29882     (emit-indent *(ebp+8) *Curr-block-depth)
29883     (write-buffered *(ebp+8) "(allocate Heap ")
29884     (addr-handle-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
29885     (write-int32-hex-buffered *(ebp+8) %eax)
29886     (emit-subx-call-operand *(ebp+8) %edi)
29887     (write-buffered *(ebp+8) ")\n")
29888 $translate-mu-allocate-stmt:end:
29889     # . restore registers
29890     5f/pop-to-edi
29891     5e/pop-to-esi
29892     58/pop-to-eax
29893     # . epilogue
29894     89/<- %esp 5/r32/ebp
29895     5d/pop-to-ebp
29896     c3/return
29897 
29898 addr-handle-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
29899     # . prologue
29900     55/push-ebp
29901     89/<- %ebp 4/r32/esp
29902     # var t/eax: (addr type-tree) = s->value->type
29903     8b/-> *(ebp+8) 0/r32/eax
29904     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29905     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
29906     # TODO: check eax != 0
29907     # TODO: check !t->is-atom?
29908     # TODO: check t->left == addr
29909     # t = t->right
29910 $addr-handle-payload-size:skip-addr:
29911     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
29912     # TODO: check eax != 0
29913     # TODO: check !t->is-atom?
29914     # TODO: check t->left == handle
29915     # t = t->right
29916 $addr-handle-payload-size:skip-handle:
29917     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
29918     # TODO: check eax != 0
29919     # if !t->is-atom? t = t->left
29920     81 7/subop/compare *eax 0/imm32/false
29921     {
29922       75/jump-if-!= break/disp8
29923       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
29924     }
29925     # TODO: check t->is-atom?
29926     # return size(t->value)
29927     (size-of-type-id *(eax+4))  # Type-tree-value => eax
29928 $addr-handle-payload-size:end:
29929     # . epilogue
29930     89/<- %esp 5/r32/ebp
29931     5d/pop-to-ebp
29932     c3/return
29933 
29934 addr-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
29935     # . prologue
29936     55/push-ebp
29937     89/<- %ebp 4/r32/esp
29938     # var t/eax: (addr type-tree) = s->value->type
29939     8b/-> *(ebp+8) 0/r32/eax
29940     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29941     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
29942     # TODO: check eax != 0
29943     # TODO: check !t->is-atom?
29944     # TODO: check t->left == addr
29945     # t = t->right
29946 $addr-payload-size:skip-addr:
29947     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
29948     # TODO: check eax != 0
29949     # if !t->is-atom? t = t->left
29950     81 7/subop/compare *eax 0/imm32/false
29951     {
29952       75/jump-if-!= break/disp8
29953       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
29954     }
29955     # TODO: check t->is-atom?
29956     # return size(t->value)
29957     (size-of-type-id *(eax+4))  # Type-tree-value => eax
29958 $addr-payload-size:end:
29959     # . epilogue
29960     89/<- %esp 5/r32/ebp
29961     5d/pop-to-ebp
29962     c3/return
29963 
29964 translate-mu-populate-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
29965     # . prologue
29966     55/push-ebp
29967     89/<- %ebp 4/r32/esp
29968     # . save registers
29969     50/push-eax
29970     51/push-ecx
29971     56/push-esi
29972     57/push-edi
29973     # esi = stmt
29974     8b/-> *(ebp+0xc) 6/r32/esi
29975     # var target/edi: (addr stmt-var) = stmt->inouts[0]
29976     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29977     89/<- %edi 0/r32/eax
29978     # var len/ecx: (addr stmt-var) = stmt->inouts[1]
29979     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
29980     89/<- %ecx 0/r32/eax
29981     #
29982     (emit-indent *(ebp+8) *Curr-block-depth)
29983     (write-buffered *(ebp+8) "(allocate-array2 Heap ")
29984     (addr-handle-array-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
29985     (write-int32-hex-buffered *(ebp+8) %eax)
29986     (emit-subx-call-operand *(ebp+8) %ecx)
29987     (emit-subx-call-operand *(ebp+8) %edi)
29988     (write-buffered *(ebp+8) ")\n")
29989 $translate-mu-populate-stmt:end:
29990     # . restore registers
29991     5f/pop-to-edi
29992     5e/pop-to-esi
29993     59/pop-to-ecx
29994     58/pop-to-eax
29995     # . epilogue
29996     89/<- %esp 5/r32/ebp
29997     5d/pop-to-ebp
29998     c3/return
29999 
30000 translate-mu-populate-stream-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
30001     # . prologue
30002     55/push-ebp
30003     89/<- %ebp 4/r32/esp
30004     # . save registers
30005     50/push-eax
30006     51/push-ecx
30007     56/push-esi
30008     57/push-edi
30009     # esi = stmt
30010     8b/-> *(ebp+0xc) 6/r32/esi
30011     # var target/edi: (addr stmt-var) = stmt->inouts[0]
30012     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
30013     89/<- %edi 0/r32/eax
30014     # var len/ecx: (addr stmt-var) = stmt->inouts[1]
30015     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
30016     89/<- %ecx 0/r32/eax
30017     #
30018     (emit-indent *(ebp+8) *Curr-block-depth)
30019     (write-buffered *(ebp+8) "(new-stream Heap ")
30020     (addr-handle-stream-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
30021     (write-int32-hex-buffered *(ebp+8) %eax)
30022     (emit-subx-call-operand *(ebp+8) %ecx)
30023     (emit-subx-call-operand *(ebp+8) %edi)
30024     (write-buffered *(ebp+8) ")\n")
30025 $translate-mu-populate-stream-stmt:end:
30026     # . restore registers
30027     5f/pop-to-edi
30028     5e/pop-to-esi
30029     59/pop-to-ecx
30030     58/pop-to-eax
30031     # . epilogue
30032     89/<- %esp 5/r32/ebp
30033     5d/pop-to-ebp
30034     c3/return
30035 
30036 translate-mu-read-from-stream-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
30037     # . prologue
30038     55/push-ebp
30039     89/<- %ebp 4/r32/esp
30040     # . save registers
30041     50/push-eax
30042     51/push-ecx
30043     56/push-esi
30044     57/push-edi
30045     # esi = stmt
30046     8b/-> *(ebp+0xc) 6/r32/esi
30047     # var stream/ecx: (addr stmt-var) = stmt->inouts[0]
30048     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
30049     89/<- %ecx 0/r32/eax
30050     # var target/edi: (addr stmt-var) = stmt->inouts[1]
30051     (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
30052     89/<- %edi 0/r32/eax
30053     #
30054     (emit-indent *(ebp+8) *Curr-block-depth)
30055     (write-buffered *(ebp+8) "(read-from-stream")
30056     (emit-subx-call-operand *(ebp+8) %ecx)
30057     (emit-subx-call-operand *(ebp+8) %edi)
30058     (write-buffered *(ebp+8) Space)
30059     (addr-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
30060     (write-int32-hex-buffered *(ebp+8) %eax)
30061     (write-buffered *(ebp+8) ")\n")
30062 $translate-mu-read-from-stream-stmt:end:
30063     # . restore registers
30064     5f/pop-to-edi
30065     5e/pop-to-esi
30066     59/pop-to-ecx
30067     58/pop-to-eax
30068     # . epilogue
30069     89/<- %esp 5/r32/ebp
30070     5d/pop-to-ebp
30071     c3/return
30072 
30073 translate-mu-write-to-stream-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
30074     # . prologue
30075     55/push-ebp
30076     89/<- %ebp 4/r32/esp
30077     # . save registers
30078     50/push-eax
30079     51/push-ecx
30080     56/push-esi
30081     57/push-edi
30082     # esi = stmt
30083     8b/-> *(ebp+0xc) 6/r32/esi
30084     # var stream/ecx: (addr stmt-var) = stmt->inouts[0]
30085     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
30086     89/<- %ecx 0/r32/eax
30087     # var target/edi: (addr stmt-var) = stmt->inouts[1]
30088     (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
30089     89/<- %edi 0/r32/eax
30090     #
30091     (emit-indent *(ebp+8) *Curr-block-depth)
30092     (write-buffered *(ebp+8) "(write-to-stream")
30093     (emit-subx-call-operand *(ebp+8) %ecx)
30094     (flush *(ebp+8))
30095     (emit-subx-call-operand *(ebp+8) %edi)
30096     (flush *(ebp+8))
30097     (write-buffered *(ebp+8) Space)
30098     (flush *(ebp+8))
30099     (addr-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
30100     (write-int32-hex-buffered *(ebp+8) %eax)
30101     (write-buffered *(ebp+8) ")\n")
30102 $translate-mu-write-to-stream-stmt:end:
30103     # . restore registers
30104     5f/pop-to-edi
30105     5e/pop-to-esi
30106     59/pop-to-ecx
30107     58/pop-to-eax
30108     # . epilogue
30109     89/<- %esp 5/r32/ebp
30110     5d/pop-to-ebp
30111     c3/return
30112 
30113 addr-handle-array-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
30114     # . prologue
30115     55/push-ebp
30116     89/<- %ebp 4/r32/esp
30117     # var t/eax: (addr type-tree) = s->value->type
30118     8b/-> *(ebp+8) 0/r32/eax
30119     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
30120     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
30121     # TODO: check eax != 0
30122     # TODO: check !t->is-atom?
30123     # TODO: check t->left == addr
30124     # t = t->right
30125 $addr-handle-array-payload-size:skip-addr:
30126     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
30127     # TODO: check eax != 0
30128     # TODO: check !t->is-atom?
30129     # TODO: check t->left == handle
30130     # t = t->right
30131 $addr-handle-array-payload-size:skip-handle:
30132     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
30133     # TODO: check eax != 0
30134     # TODO: check !t->is-atom?
30135     # TODO: check t->left == array
30136     # t = t->right
30137 $addr-handle-array-payload-size:skip-array:
30138     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
30139     # TODO: check eax != 0
30140     # if !t->is-atom? t = t->left
30141     81 7/subop/compare *eax 0/imm32/false
30142     {
30143       75/jump-if-!= break/disp8
30144       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
30145     }
30146 $addr-handle-array-payload-size:compute-size:
30147     # TODO: check t->is-atom?
30148     # return size(t->value)
30149     (size-of-type-id-as-array-element *(eax+4))  # Type-tree-value => eax
30150 $addr-handle-array-payload-size:end:
30151     # . epilogue
30152     89/<- %esp 5/r32/ebp
30153     5d/pop-to-ebp
30154     c3/return
30155 
30156 addr-handle-stream-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
30157     # . prologue
30158     55/push-ebp
30159     89/<- %ebp 4/r32/esp
30160     # var t/eax: (addr type-tree) = s->value->type
30161     8b/-> *(ebp+8) 0/r32/eax
30162     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
30163     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
30164     # TODO: check eax != 0
30165     # TODO: check !t->is-atom?
30166     # TODO: check t->left == addr
30167     # t = t->right
30168 $addr-handle-stream-payload-size:skip-addr:
30169     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
30170     # TODO: check eax != 0
30171     # TODO: check !t->is-atom?
30172     # TODO: check t->left == handle
30173     # t = t->right
30174 $addr-handle-stream-payload-size:skip-handle:
30175     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
30176     # TODO: check eax != 0
30177     # TODO: check !t->is-atom?
30178     # TODO: check t->left == stream
30179     # t = t->right
30180 $addr-handle-stream-payload-size:skip-stream:
30181     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
30182     # TODO: check eax != 0
30183     # if !t->is-atom? t = t->left
30184     81 7/subop/compare *eax 0/imm32/false
30185     {
30186       75/jump-if-!= break/disp8
30187       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
30188     }
30189 $addr-handle-stream-payload-size:compute-size:
30190     # TODO: check t->is-atom?
30191     # return size(t->value)
30192     (size-of-type-id-as-array-element *(eax+4))  # Type-tree-value => eax
30193 $addr-handle-stream-payload-size:end:
30194     # . epilogue
30195     89/<- %esp 5/r32/ebp
30196     5d/pop-to-ebp
30197     c3/return
30198 
30199 power-of-2?:  # n: int, err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: boolean
30200     # precondition: n is positive
30201     # . prologue
30202     55/push-ebp
30203     89/<- %ebp 4/r32/esp
30204     # eax = n
30205     8b/-> *(ebp+8) 0/r32/eax
30206     # if (n < 0) abort
30207     3d/compare-eax-with 0/imm32
30208     0f 8c/jump-if-< $power-of-2?:abort/disp32
30209     # var tmp/eax: int = n-1
30210     48/decrement-eax
30211     # var tmp2/eax: int = n & tmp
30212     23/and-> *(ebp+8) 0/r32/eax
30213     # return (tmp2 == 0)
30214     3d/compare-eax-and 0/imm32
30215     0f 94/set-byte-if-= %al
30216     81 4/subop/and %eax 0xff/imm32
30217 $power-of-2?:end:
30218     # . epilogue
30219     89/<- %esp 5/r32/ebp
30220     5d/pop-to-ebp
30221     c3/return
30222 
30223 $power-of-2?:abort:
30224     (write-buffered *(ebp+0xc) "power-of-2?: negative number\n")
30225     (flush *(ebp+0xc))
30226     (stop *(ebp+0x10) 1)
30227     # never gets here
30228 
30229 num-shift-rights:  # n: int -> result/eax: int
30230     # precondition: n is a positive power of 2
30231     # . prologue
30232     55/push-ebp
30233     89/<- %ebp 4/r32/esp
30234     # . save registers
30235     51/push-ecx
30236     # var curr/ecx: int = n
30237     8b/-> *(ebp+8) 1/r32/ecx
30238     # result = 0
30239     b8/copy-to-eax 0/imm32
30240     {
30241       # if (curr <= 1) break
30242       81 7/subop/compare %ecx 1/imm32
30243       7e/jump-if-<= break/disp8
30244       40/increment-eax
30245       c1/shift 5/subop/arithmetic-right %ecx 1/imm8
30246       eb/jump loop/disp8
30247     }
30248 $num-shift-rights:end:
30249     # . restore registers
30250     59/pop-to-ecx
30251     # . epilogue
30252     89/<- %esp 5/r32/ebp
30253     5d/pop-to-ebp
30254     c3/return
30255 
30256 mu-get-offset:  # stmt: (addr stmt) -> result/eax: int
30257     # . prologue
30258     55/push-ebp
30259     89/<- %ebp 4/r32/esp
30260     # var second-inout/eax: (addr stmt-var) = stmt->inouts->next
30261     8b/-> *(ebp+8) 0/r32/eax
30262     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
30263     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
30264     # var output-var/eax: (addr var) = second-inout->value
30265     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
30266 #?     (write-buffered Stderr "mu-get-offset: ")
30267 #?     (write-int32-hex-buffered Stderr %eax)
30268 #?     (write-buffered Stderr " name: ")
30269 #?     50/push-eax
30270 #?     (lookup *eax *(eax+4))  # Var-name
30271 #?     (write-buffered Stderr %eax)
30272 #?     58/pop-to-eax
30273 #?     (write-buffered Stderr Newline)
30274 #?     (flush Stderr)
30275     # return output-var->stack-offset
30276     8b/-> *(eax+0x14) 0/r32/eax  # Var-offset
30277 #?     (write-buffered Stderr "=> ")
30278 #?     (write-int32-hex-buffered Stderr %eax)
30279 #?     (write-buffered Stderr Newline)
30280 #?     (flush Stderr)
30281 $emit-get-offset:end:
30282     # . epilogue
30283     89/<- %esp 5/r32/ebp
30284     5d/pop-to-ebp
30285     c3/return
30286 
30287 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)
30288     # . prologue
30289     55/push-ebp
30290     89/<- %ebp 4/r32/esp
30291     # . save registers
30292     50/push-eax
30293     51/push-ecx
30294     56/push-esi
30295     # esi = block
30296     8b/-> *(ebp+0xc) 6/r32/esi
30297     # block->var->block-depth = *Curr-block-depth
30298     (lookup *(esi+0xc) *(esi+0x10))  # Block-var Block-var => eax
30299     8b/-> *Curr-block-depth 1/r32/ecx
30300     89/<- *(eax+0x10) 1/r32/ecx  # Var-block-depth
30301     # var stmts/eax: (addr list stmt) = lookup(block->statements)
30302     (lookup *(esi+4) *(esi+8))  # Block-stmts Block-stmts => eax
30303     #
30304     {
30305 $emit-subx-block:check-empty:
30306       3d/compare-eax-and 0/imm32
30307       0f 84/jump-if-= break/disp32
30308       (emit-indent *(ebp+8) *Curr-block-depth)
30309       (write-buffered *(ebp+8) "{\n")
30310       # var v/ecx: (addr var) = lookup(block->var)
30311       (lookup *(esi+0xc) *(esi+0x10))  # Block-var Block-var => eax
30312       89/<- %ecx 0/r32/eax
30313       #
30314       (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
30315       (write-buffered *(ebp+8) %eax)
30316       (write-buffered *(ebp+8) ":loop:\n")
30317       ff 0/subop/increment *Curr-block-depth
30318       (push *(ebp+0x10) *(esi+0xc))  # Block-var
30319       (push *(ebp+0x10) *(esi+0x10))  # Block-var
30320       (push *(ebp+0x10) 0)  # false
30321       # emit block->statements
30322       (lookup *(esi+4) *(esi+8))  # Block-stmts Block-stmts => eax
30323       (emit-subx-stmt-list *(ebp+8) %eax *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
30324       (pop *(ebp+0x10))  # => eax
30325       (pop *(ebp+0x10))  # => eax
30326       (pop *(ebp+0x10))  # => eax
30327       ff 1/subop/decrement *Curr-block-depth
30328       (emit-indent *(ebp+8) *Curr-block-depth)
30329       (write-buffered *(ebp+8) "}\n")
30330       (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
30331       (write-buffered *(ebp+8) %eax)
30332       (write-buffered *(ebp+8) ":break:\n")
30333     }
30334 $emit-subx-block:end:
30335     # . restore registers
30336     5e/pop-to-esi
30337     59/pop-to-ecx
30338     58/pop-to-eax
30339     # . epilogue
30340     89/<- %esp 5/r32/ebp
30341     5d/pop-to-ebp
30342     c3/return
30343 
30344 # Primitives supported
30345 # See mu_instructions for a summary of this linked-list data structure.
30346 #
30347 # For each operation, put variants with hard-coded registers before flexible ones.
30348 #
30349 # Unfortunately, our restrictions on addresses require that various fields in
30350 # primitives be handles, which complicates these definitions.
30351 #   - we need to insert dummy fields all over the place for fake alloc-ids
30352 #   - we can't use our syntax sugar of quoted literals for string fields
30353 #
30354 # Fake alloc-ids are needed because our type definitions up top require
30355 # handles but it's clearer to statically allocate these long-lived objects.
30356 # Fake alloc-ids are perfectly safe, but they can't be reclaimed.
30357 #
30358 # Every 'object' below starts with a fake alloc-id. It may also contain other
30359 # fake alloc-ids for various handle fields.
30360 #
30361 # I think of objects starting with a fake alloc-id as having type 'payload'.
30362 # It's not really intended to be created dynamically; for that use `allocate`
30363 # as usual.
30364 #
30365 # Idea for a notation to simplify such definitions:
30366 #   _Primitive-increment-eax:  # (payload primitive)
30367 #     0x11/alloc-id:fake:payload
30368 #     0x11 @(0x11 "increment")  # name
30369 #     0 0                       # inouts
30370 #     0x11 @(0x11/payload
30371 #            0x11 @(0x11/payload  # List-value
30372 #                   0 0             # Var-name
30373 #                   0x11 @(0x11     # Var-type
30374 #                          1/is-atom
30375 #                          1/value 0/unused   # Type-tree-left
30376 #                          0 0                # Type-tree-right
30377 #                         )
30378 #                   1               # block-depth
30379 #                   0               # stack-offset
30380 #                   0x11 @(0x11 "eax")  # Var-register
30381 #                  )
30382 #            0 0)                 # List-next
30383 #     ...
30384 #     _Primitive-increment-ecx/imm32/next
30385 #   ...
30386 # Awfully complex and non-obvious. But also clearly signals there's something
30387 # to learn here, so may be worth trying.
30388 #
30389 # '@' is just an initial thought. Punctuation used so far in Mu: () * % # / "
30390 #
30391 # For now we'll continue to just use comments and manually ensure they stay up
30392 # to date.
30393 == data
30394 Primitives:  # (addr primitive)
30395 # - increment/decrement
30396 _Primitive-increment-eax:  # (addr primitive)
30397     # var/eax <- increment => 40/increment-eax
30398     0x11/imm32/alloc-id:fake
30399     _string-increment/imm32/name
30400     0/imm32/no-inouts
30401     0/imm32/no-inouts
30402     0x11/imm32/alloc-id:fake
30403     Single-int-var-in-eax/imm32/outputs
30404     0x11/imm32/alloc-id:fake
30405     _string_40_increment_eax/imm32/subx-name
30406     0/imm32/no-rm32
30407     0/imm32/no-r32
30408     0/imm32/no-imm32
30409     0/imm32/no-imm8
30410     0/imm32/no-disp32
30411     0/imm32/no-xm32
30412     0/imm32/no-x32
30413     0x11/imm32/alloc-id:fake
30414     _Primitive-increment-ecx/imm32/next
30415 _Primitive-increment-ecx:  # (payload primitive)
30416     0x11/imm32/alloc-id:fake:payload
30417     # var/ecx <- increment => 41/increment-ecx
30418     0x11/imm32/alloc-id:fake
30419     _string-increment/imm32/name
30420     0/imm32/no-inouts
30421     0/imm32/no-inouts
30422     0x11/imm32/alloc-id:fake
30423     Single-int-var-in-ecx/imm32/outputs
30424     0x11/imm32/alloc-id:fake
30425     _string_41_increment_ecx/imm32/subx-name
30426     0/imm32/no-rm32
30427     0/imm32/no-r32
30428     0/imm32/no-imm32
30429     0/imm32/no-imm8
30430     0/imm32/no-disp32
30431     0/imm32/no-xm32
30432     0/imm32/no-x32
30433     0x11/imm32/alloc-id:fake
30434     _Primitive-increment-edx/imm32/next
30435 _Primitive-increment-edx:  # (payload primitive)
30436     0x11/imm32/alloc-id:fake:payload
30437     # var/edx <- increment => 42/increment-edx
30438     0x11/imm32/alloc-id:fake
30439     _string-increment/imm32/name
30440     0/imm32/no-inouts
30441     0/imm32/no-inouts
30442     0x11/imm32/alloc-id:fake
30443     Single-int-var-in-edx/imm32/outputs
30444     0x11/imm32/alloc-id:fake
30445     _string_42_increment_edx/imm32/subx-name
30446     0/imm32/no-rm32
30447     0/imm32/no-r32
30448     0/imm32/no-imm32
30449     0/imm32/no-imm8
30450     0/imm32/no-disp32
30451     0/imm32/no-xm32
30452     0/imm32/no-x32
30453     0x11/imm32/alloc-id:fake
30454     _Primitive-increment-ebx/imm32/next
30455 _Primitive-increment-ebx:  # (payload primitive)
30456     0x11/imm32/alloc-id:fake:payload
30457     # var/ebx <- increment => 43/increment-ebx
30458     0x11/imm32/alloc-id:fake
30459     _string-increment/imm32/name
30460     0/imm32/no-inouts
30461     0/imm32/no-inouts
30462     0x11/imm32/alloc-id:fake
30463     Single-int-var-in-ebx/imm32/outputs
30464     0x11/imm32/alloc-id:fake
30465     _string_43_increment_ebx/imm32/subx-name
30466     0/imm32/no-rm32
30467     0/imm32/no-r32
30468     0/imm32/no-imm32
30469     0/imm32/no-imm8
30470     0/imm32/no-disp32
30471     0/imm32/no-xm32
30472     0/imm32/no-x32
30473     0x11/imm32/alloc-id:fake
30474     _Primitive-increment-esi/imm32/next
30475 _Primitive-increment-esi:  # (payload primitive)
30476     0x11/imm32/alloc-id:fake:payload
30477     # var/esi <- increment => 46/increment-esi
30478     0x11/imm32/alloc-id:fake
30479     _string-increment/imm32/name
30480     0/imm32/no-inouts
30481     0/imm32/no-inouts
30482     0x11/imm32/alloc-id:fake
30483     Single-int-var-in-esi/imm32/outputs
30484     0x11/imm32/alloc-id:fake
30485     _string_46_increment_esi/imm32/subx-name
30486     0/imm32/no-rm32
30487     0/imm32/no-r32
30488     0/imm32/no-imm32
30489     0/imm32/no-imm8
30490     0/imm32/no-disp32
30491     0/imm32/no-xm32
30492     0/imm32/no-x32
30493     0x11/imm32/alloc-id:fake
30494     _Primitive-increment-edi/imm32/next
30495 _Primitive-increment-edi:  # (payload primitive)
30496     0x11/imm32/alloc-id:fake:payload
30497     # var/edi <- increment => 47/increment-edi
30498     0x11/imm32/alloc-id:fake
30499     _string-increment/imm32/name
30500     0/imm32/no-inouts
30501     0/imm32/no-inouts
30502     0x11/imm32/alloc-id:fake
30503     Single-int-var-in-edi/imm32/outputs
30504     0x11/imm32/alloc-id:fake
30505     _string_47_increment_edi/imm32/subx-name
30506     0/imm32/no-rm32
30507     0/imm32/no-r32
30508     0/imm32/no-imm32
30509     0/imm32/no-imm8
30510     0/imm32/no-disp32
30511     0/imm32/no-xm32
30512     0/imm32/no-x32
30513     0x11/imm32/alloc-id:fake
30514     _Primitive-decrement-eax/imm32/next
30515 _Primitive-decrement-eax:  # (payload primitive)
30516     0x11/imm32/alloc-id:fake:payload
30517     # var/eax <- decrement => 48/decrement-eax
30518     0x11/imm32/alloc-id:fake
30519     _string-decrement/imm32/name
30520     0/imm32/no-inouts
30521     0/imm32/no-inouts
30522     0x11/imm32/alloc-id:fake
30523     Single-int-var-in-eax/imm32/outputs
30524     0x11/imm32/alloc-id:fake
30525     _string_48_decrement_eax/imm32/subx-name
30526     0/imm32/no-rm32
30527     0/imm32/no-r32
30528     0/imm32/no-imm32
30529     0/imm32/no-imm8
30530     0/imm32/no-disp32
30531     0/imm32/no-xm32
30532     0/imm32/no-x32
30533     0x11/imm32/alloc-id:fake
30534     _Primitive-decrement-ecx/imm32/next
30535 _Primitive-decrement-ecx:  # (payload primitive)
30536     0x11/imm32/alloc-id:fake:payload
30537     # var/ecx <- decrement => 49/decrement-ecx
30538     0x11/imm32/alloc-id:fake
30539     _string-decrement/imm32/name
30540     0/imm32/no-inouts
30541     0/imm32/no-inouts
30542     0x11/imm32/alloc-id:fake
30543     Single-int-var-in-ecx/imm32/outputs
30544     0x11/imm32/alloc-id:fake
30545     _string_49_decrement_ecx/imm32/subx-name
30546     0/imm32/no-rm32
30547     0/imm32/no-r32
30548     0/imm32/no-imm32
30549     0/imm32/no-imm8
30550     0/imm32/no-disp32
30551     0/imm32/no-xm32
30552     0/imm32/no-x32
30553     0x11/imm32/alloc-id:fake
30554     _Primitive-decrement-edx/imm32/next
30555 _Primitive-decrement-edx:  # (payload primitive)
30556     0x11/imm32/alloc-id:fake:payload
30557     # var/edx <- decrement => 4a/decrement-edx
30558     0x11/imm32/alloc-id:fake
30559     _string-decrement/imm32/name
30560     0/imm32/no-inouts
30561     0/imm32/no-inouts
30562     0x11/imm32/alloc-id:fake
30563     Single-int-var-in-edx/imm32/outputs
30564     0x11/imm32/alloc-id:fake
30565     _string_4a_decrement_edx/imm32/subx-name
30566     0/imm32/no-rm32
30567     0/imm32/no-r32
30568     0/imm32/no-imm32
30569     0/imm32/no-imm8
30570     0/imm32/no-disp32
30571     0/imm32/no-xm32
30572     0/imm32/no-x32
30573     0x11/imm32/alloc-id:fake
30574     _Primitive-decrement-ebx/imm32/next
30575 _Primitive-decrement-ebx:  # (payload primitive)
30576     0x11/imm32/alloc-id:fake:payload
30577     # var/ebx <- decrement => 4b/decrement-ebx
30578     0x11/imm32/alloc-id:fake
30579     _string-decrement/imm32/name
30580     0/imm32/no-inouts
30581     0/imm32/no-inouts
30582     0x11/imm32/alloc-id:fake
30583     Single-int-var-in-ebx/imm32/outputs
30584     0x11/imm32/alloc-id:fake
30585     _string_4b_decrement_ebx/imm32/subx-name
30586     0/imm32/no-rm32
30587     0/imm32/no-r32
30588     0/imm32/no-imm32
30589     0/imm32/no-imm8
30590     0/imm32/no-disp32
30591     0/imm32/no-xm32
30592     0/imm32/no-x32
30593     0x11/imm32/alloc-id:fake
30594     _Primitive-decrement-esi/imm32/next
30595 _Primitive-decrement-esi:  # (payload primitive)
30596     0x11/imm32/alloc-id:fake:payload
30597     # var/esi <- decrement => 4e/decrement-esi
30598     0x11/imm32/alloc-id:fake
30599     _string-decrement/imm32/name
30600     0/imm32/no-inouts
30601     0/imm32/no-inouts
30602     0x11/imm32/alloc-id:fake
30603     Single-int-var-in-esi/imm32/outputs
30604     0x11/imm32/alloc-id:fake
30605     _string_4e_decrement_esi/imm32/subx-name
30606     0/imm32/no-rm32
30607     0/imm32/no-r32
30608     0/imm32/no-imm32
30609     0/imm32/no-imm8
30610     0/imm32/no-disp32
30611     0/imm32/no-xm32
30612     0/imm32/no-x32
30613     0x11/imm32/alloc-id:fake
30614     _Primitive-decrement-edi/imm32/next
30615 _Primitive-decrement-edi:  # (payload primitive)
30616     0x11/imm32/alloc-id:fake:payload
30617     # var/edi <- decrement => 4f/decrement-edi
30618     0x11/imm32/alloc-id:fake
30619     _string-decrement/imm32/name
30620     0/imm32/no-inouts
30621     0/imm32/no-inouts
30622     0x11/imm32/alloc-id:fake
30623     Single-int-var-in-edi/imm32/outputs
30624     0x11/imm32/alloc-id:fake
30625     _string_4f_decrement_edi/imm32/subx-name
30626     0/imm32/no-rm32
30627     0/imm32/no-r32
30628     0/imm32/no-imm32
30629     0/imm32/no-imm8
30630     0/imm32/no-disp32
30631     0/imm32/no-xm32
30632     0/imm32/no-x32
30633     0x11/imm32/alloc-id:fake
30634     _Primitive-increment-mem/imm32/next
30635 _Primitive-increment-mem:  # (payload primitive)
30636     0x11/imm32/alloc-id:fake:payload
30637     # increment var => ff 0/subop/increment *(ebp+__)
30638     0x11/imm32/alloc-id:fake
30639     _string-increment/imm32/name
30640     0x11/imm32/alloc-id:fake
30641     Single-int-var-in-mem/imm32/inouts
30642     0/imm32/no-outputs
30643     0/imm32/no-outputs
30644     0x11/imm32/alloc-id:fake
30645     _string_ff_subop_increment/imm32/subx-name
30646     1/imm32/rm32-is-first-inout
30647     0/imm32/no-r32
30648     0/imm32/no-imm32
30649     0/imm32/no-imm8
30650     0/imm32/no-disp32
30651     0/imm32/no-xm32
30652     0/imm32/no-x32
30653     0x11/imm32/alloc-id:fake
30654     _Primitive-increment-reg/imm32/next
30655 _Primitive-increment-reg:  # (payload primitive)
30656     0x11/imm32/alloc-id:fake:payload
30657     # var/reg <- increment => ff 0/subop/increment %__
30658     0x11/imm32/alloc-id:fake
30659     _string-increment/imm32/name
30660     0/imm32/no-inouts
30661     0/imm32/no-inouts
30662     0x11/imm32/alloc-id:fake
30663     Single-int-var-in-some-register/imm32/outputs
30664     0x11/imm32/alloc-id:fake
30665     _string_ff_subop_increment/imm32/subx-name
30666     3/imm32/rm32-is-first-output
30667     0/imm32/no-r32
30668     0/imm32/no-imm32
30669     0/imm32/no-imm8
30670     0/imm32/no-disp32
30671     0/imm32/no-xm32
30672     0/imm32/no-x32
30673     0x11/imm32/alloc-id:fake
30674     _Primitive-decrement-mem/imm32/next
30675 _Primitive-decrement-mem:  # (payload primitive)
30676     0x11/imm32/alloc-id:fake:payload
30677     # decrement var => ff 1/subop/decrement *(ebp+__)
30678     0x11/imm32/alloc-id:fake
30679     _string-decrement/imm32/name
30680     0x11/imm32/alloc-id:fake
30681     Single-int-var-in-mem/imm32/inouts
30682     0/imm32/no-outputs
30683     0/imm32/no-outputs
30684     0x11/imm32/alloc-id:fake
30685     _string_ff_subop_decrement/imm32/subx-name
30686     1/imm32/rm32-is-first-inout
30687     0/imm32/no-r32
30688     0/imm32/no-imm32
30689     0/imm32/no-imm8
30690     0/imm32/no-disp32
30691     0/imm32/no-xm32
30692     0/imm32/no-x32
30693     0x11/imm32/alloc-id:fake
30694     _Primitive-decrement-reg/imm32/next
30695 _Primitive-decrement-reg:  # (payload primitive)
30696     0x11/imm32/alloc-id:fake:payload
30697     # var/reg <- decrement => ff 1/subop/decrement %__
30698     0x11/imm32/alloc-id:fake
30699     _string-decrement/imm32/name
30700     0/imm32/no-inouts
30701     0/imm32/no-inouts
30702     0x11/imm32/alloc-id:fake
30703     Single-int-var-in-some-register/imm32/outputs
30704     0x11/imm32/alloc-id:fake
30705     _string_ff_subop_decrement/imm32/subx-name
30706     3/imm32/rm32-is-first-output
30707     0/imm32/no-r32
30708     0/imm32/no-imm32
30709     0/imm32/no-imm8
30710     0/imm32/no-disp32
30711     0/imm32/no-xm32
30712     0/imm32/no-x32
30713     0x11/imm32/alloc-id:fake
30714     _Primitive-add-to-eax/imm32/next
30715 # - add
30716 _Primitive-add-to-eax:  # (payload primitive)
30717     0x11/imm32/alloc-id:fake:payload
30718     # var/eax <- add lit => 05/add-to-eax lit/imm32
30719     0x11/imm32/alloc-id:fake
30720     _string-add/imm32/name
30721     0x11/imm32/alloc-id:fake
30722     Single-lit-var/imm32/inouts
30723     0x11/imm32/alloc-id:fake
30724     Single-int-var-in-eax/imm32/outputs
30725     0x11/imm32/alloc-id:fake
30726     _string_05_add_to_eax/imm32/subx-name
30727     0/imm32/no-rm32
30728     0/imm32/no-r32
30729     1/imm32/imm32-is-first-inout
30730     0/imm32/no-imm8
30731     0/imm32/no-disp32
30732     0/imm32/no-xm32
30733     0/imm32/no-x32
30734     0x11/imm32/alloc-id:fake
30735     _Primitive-add-reg-to-reg/imm32/next
30736 _Primitive-add-reg-to-reg:  # (payload primitive)
30737     0x11/imm32/alloc-id:fake:payload
30738     # var1/reg <- add var2/reg => 01/add-to var1/rm32 var2/r32
30739     0x11/imm32/alloc-id:fake
30740     _string-add/imm32/name
30741     0x11/imm32/alloc-id:fake
30742     Single-int-var-in-some-register/imm32/inouts
30743     0x11/imm32/alloc-id:fake
30744     Single-int-var-in-some-register/imm32/outputs
30745     0x11/imm32/alloc-id:fake
30746     _string_01_add_to/imm32/subx-name
30747     3/imm32/rm32-is-first-output
30748     1/imm32/r32-is-first-inout
30749     0/imm32/no-imm32
30750     0/imm32/no-imm8
30751     0/imm32/no-disp32
30752     0/imm32/no-xm32
30753     0/imm32/no-x32
30754     0x11/imm32/alloc-id:fake
30755     _Primitive-add-reg-to-mem/imm32/next
30756 _Primitive-add-reg-to-mem:  # (payload primitive)
30757     0x11/imm32/alloc-id:fake:payload
30758     # add-to var1 var2/reg => 01/add-to var1 var2/r32
30759     0x11/imm32/alloc-id:fake
30760     _string-add-to/imm32/name
30761     0x11/imm32/alloc-id:fake
30762     Two-args-int-stack-int-reg/imm32/inouts
30763     0/imm32/no-outputs
30764     0/imm32/no-outputs
30765     0x11/imm32/alloc-id:fake
30766     _string_01_add_to/imm32/subx-name
30767     1/imm32/rm32-is-first-inout
30768     2/imm32/r32-is-second-inout
30769     0/imm32/no-imm32
30770     0/imm32/no-imm8
30771     0/imm32/no-disp32
30772     0/imm32/no-xm32
30773     0/imm32/no-x32
30774     0x11/imm32/alloc-id:fake
30775     _Primitive-add-mem-to-reg/imm32/next
30776 _Primitive-add-mem-to-reg:  # (payload primitive)
30777     0x11/imm32/alloc-id:fake:payload
30778     # var1/reg <- add var2 => 03/add var2/rm32 var1/r32
30779     0x11/imm32/alloc-id:fake
30780     _string-add/imm32/name
30781     0x11/imm32/alloc-id:fake
30782     Single-int-var-in-mem/imm32/inouts
30783     0x11/imm32/alloc-id:fake
30784     Single-int-var-in-some-register/imm32/outputs
30785     0x11/imm32/alloc-id:fake
30786     _string_03_add/imm32/subx-name
30787     1/imm32/rm32-is-first-inout
30788     3/imm32/r32-is-first-output
30789     0/imm32/no-imm32
30790     0/imm32/no-imm8
30791     0/imm32/no-disp32
30792     0/imm32/no-xm32
30793     0/imm32/no-x32
30794     0x11/imm32/alloc-id:fake
30795     _Primitive-add-lit-to-reg/imm32/next
30796 _Primitive-add-lit-to-reg:  # (payload primitive)
30797     0x11/imm32/alloc-id:fake:payload
30798     # var1/reg <- add lit => 81 0/subop/add var1/rm32 lit/imm32
30799     0x11/imm32/alloc-id:fake
30800     _string-add/imm32/name
30801     0x11/imm32/alloc-id:fake
30802     Single-lit-var/imm32/inouts
30803     0x11/imm32/alloc-id:fake
30804     Single-int-var-in-some-register/imm32/outputs
30805     0x11/imm32/alloc-id:fake
30806     _string_81_subop_add/imm32/subx-name
30807     3/imm32/rm32-is-first-output
30808     0/imm32/no-r32
30809     1/imm32/imm32-is-first-inout
30810     0/imm32/no-imm8
30811     0/imm32/no-disp32
30812     0/imm32/no-xm32
30813     0/imm32/no-x32
30814     0x11/imm32/alloc-id:fake
30815     _Primitive-add-lit-to-mem/imm32/next
30816 _Primitive-add-lit-to-mem:  # (payload primitive)
30817     0x11/imm32/alloc-id:fake:payload
30818     # add-to var1, lit => 81 0/subop/add var1/rm32 lit/imm32
30819     0x11/imm32/alloc-id:fake
30820     _string-add-to/imm32/name
30821     0x11/imm32/alloc-id:fake
30822     Int-var-and-literal/imm32/inouts
30823     0/imm32/no-outputs
30824     0/imm32/no-outputs
30825     0x11/imm32/alloc-id:fake
30826     _string_81_subop_add/imm32/subx-name
30827     1/imm32/rm32-is-first-inout
30828     0/imm32/no-r32
30829     2/imm32/imm32-is-second-inout
30830     0/imm32/no-imm8
30831     0/imm32/no-disp32
30832     0/imm32/no-xm32
30833     0/imm32/no-x32
30834     0x11/imm32/alloc-id:fake
30835     _Primitive-subtract-from-eax/imm32/next
30836 # - subtract
30837 _Primitive-subtract-from-eax:  # (payload primitive)
30838     0x11/imm32/alloc-id:fake:payload
30839     # var/eax <- subtract lit => 2d/subtract-from-eax lit/imm32
30840     0x11/imm32/alloc-id:fake
30841     _string-subtract/imm32/name
30842     0x11/imm32/alloc-id:fake
30843     Single-lit-var/imm32/inouts
30844     0x11/imm32/alloc-id:fake
30845     Single-int-var-in-eax/imm32/outputs
30846     0x11/imm32/alloc-id:fake
30847     _string_2d_subtract_from_eax/imm32/subx-name
30848     0/imm32/no-rm32
30849     0/imm32/no-r32
30850     1/imm32/imm32-is-first-inout
30851     0/imm32/no-imm8
30852     0/imm32/no-disp32
30853     0/imm32/no-xm32
30854     0/imm32/no-x32
30855     0x11/imm32/alloc-id:fake
30856     _Primitive-subtract-reg-from-reg/imm32/next
30857 _Primitive-subtract-reg-from-reg:  # (payload primitive)
30858     0x11/imm32/alloc-id:fake:payload
30859     # var1/reg <- subtract var2/reg => 29/subtract-from var1/rm32 var2/r32
30860     0x11/imm32/alloc-id:fake
30861     _string-subtract/imm32/name
30862     0x11/imm32/alloc-id:fake
30863     Single-int-var-in-some-register/imm32/inouts
30864     0x11/imm32/alloc-id:fake
30865     Single-int-var-in-some-register/imm32/outputs
30866     0x11/imm32/alloc-id:fake
30867     _string_29_subtract_from/imm32/subx-name
30868     3/imm32/rm32-is-first-output
30869     1/imm32/r32-is-first-inout
30870     0/imm32/no-imm32
30871     0/imm32/no-imm8
30872     0/imm32/no-disp32
30873     0/imm32/no-xm32
30874     0/imm32/no-x32
30875     0x11/imm32/alloc-id:fake
30876     _Primitive-subtract-reg-from-mem/imm32/next
30877 _Primitive-subtract-reg-from-mem:  # (payload primitive)
30878     0x11/imm32/alloc-id:fake:payload
30879     # subtract-from var1 var2/reg => 29/subtract-from var1 var2/r32
30880     0x11/imm32/alloc-id:fake
30881     _string-subtract-from/imm32/name
30882     0x11/imm32/alloc-id:fake
30883     Two-args-int-stack-int-reg/imm32/inouts
30884     0/imm32/no-outputs
30885     0/imm32/no-outputs
30886     0x11/imm32/alloc-id:fake
30887     _string_29_subtract_from/imm32/subx-name
30888     1/imm32/rm32-is-first-inout
30889     2/imm32/r32-is-second-inout
30890     0/imm32/no-imm32
30891     0/imm32/no-imm8
30892     0/imm32/no-disp32
30893     0/imm32/no-xm32
30894     0/imm32/no-x32
30895     0x11/imm32/alloc-id:fake
30896     _Primitive-subtract-mem-from-reg/imm32/next
30897 _Primitive-subtract-mem-from-reg:  # (payload primitive)
30898     0x11/imm32/alloc-id:fake:payload
30899     # var1/reg <- subtract var2 => 2b/subtract var2/rm32 var1/r32
30900     0x11/imm32/alloc-id:fake
30901     _string-subtract/imm32/name
30902     0x11/imm32/alloc-id:fake
30903     Single-int-var-in-mem/imm32/inouts
30904     0x11/imm32/alloc-id:fake
30905     Single-int-var-in-some-register/imm32/outputs
30906     0x11/imm32/alloc-id:fake
30907     _string_2b_subtract/imm32/subx-name
30908     1/imm32/rm32-is-first-inout
30909     3/imm32/r32-is-first-output
30910     0/imm32/no-imm32
30911     0/imm32/no-imm8
30912     0/imm32/no-disp32
30913     0/imm32/no-xm32
30914     0/imm32/no-x32
30915     0x11/imm32/alloc-id:fake
30916     _Primitive-subtract-lit-from-reg/imm32/next
30917 _Primitive-subtract-lit-from-reg:  # (payload primitive)
30918     0x11/imm32/alloc-id:fake:payload
30919     # var1/reg <- subtract lit => 81 5/subop/subtract var1/rm32 lit/imm32
30920     0x11/imm32/alloc-id:fake
30921     _string-subtract/imm32/name
30922     0x11/imm32/alloc-id:fake
30923     Single-lit-var/imm32/inouts
30924     0x11/imm32/alloc-id:fake
30925     Single-int-var-in-some-register/imm32/outputs
30926     0x11/imm32/alloc-id:fake
30927     _string_81_subop_subtract/imm32/subx-name
30928     3/imm32/rm32-is-first-output
30929     0/imm32/no-r32
30930     1/imm32/imm32-is-first-inout
30931     0/imm32/no-imm8
30932     0/imm32/no-disp32
30933     0/imm32/no-xm32
30934     0/imm32/no-x32
30935     0x11/imm32/alloc-id:fake
30936     _Primitive-subtract-lit-from-mem/imm32/next
30937 _Primitive-subtract-lit-from-mem:  # (payload primitive)
30938     0x11/imm32/alloc-id:fake:payload
30939     # subtract-from var1, lit => 81 5/subop/subtract var1/rm32 lit/imm32
30940     0x11/imm32/alloc-id:fake
30941     _string-subtract-from/imm32/name
30942     0x11/imm32/alloc-id:fake
30943     Int-var-and-literal/imm32/inouts
30944     0/imm32/no-outputs
30945     0/imm32/no-outputs
30946     0x11/imm32/alloc-id:fake
30947     _string_81_subop_subtract/imm32/subx-name
30948     1/imm32/rm32-is-first-inout
30949     0/imm32/no-r32
30950     2/imm32/imm32-is-second-inout
30951     0/imm32/no-imm8
30952     0/imm32/no-disp32
30953     0/imm32/no-xm32
30954     0/imm32/no-x32
30955     0x11/imm32/alloc-id:fake
30956     _Primitive-and-with-eax/imm32/next
30957 # - and
30958 _Primitive-and-with-eax:  # (payload primitive)
30959     0x11/imm32/alloc-id:fake:payload
30960     # var/eax <- and lit => 25/and-with-eax lit/imm32
30961     0x11/imm32/alloc-id:fake
30962     _string-and/imm32/name
30963     0x11/imm32/alloc-id:fake
30964     Single-lit-var/imm32/inouts
30965     0x11/imm32/alloc-id:fake
30966     Single-int-var-in-eax/imm32/outputs
30967     0x11/imm32/alloc-id:fake
30968     _string_25_and_with_eax/imm32/subx-name
30969     0/imm32/no-rm32
30970     0/imm32/no-r32
30971     1/imm32/imm32-is-first-inout
30972     0/imm32/no-imm8
30973     0/imm32/no-disp32
30974     0/imm32/no-xm32
30975     0/imm32/no-x32
30976     0x11/imm32/alloc-id:fake
30977     _Primitive-and-reg-with-reg/imm32/next
30978 _Primitive-and-reg-with-reg:  # (payload primitive)
30979     0x11/imm32/alloc-id:fake:payload
30980     # var1/reg <- and var2/reg => 21/and-with var1/rm32 var2/r32
30981     0x11/imm32/alloc-id:fake
30982     _string-and/imm32/name
30983     0x11/imm32/alloc-id:fake
30984     Single-int-var-in-some-register/imm32/inouts
30985     0x11/imm32/alloc-id:fake
30986     Single-int-var-in-some-register/imm32/outputs
30987     0x11/imm32/alloc-id:fake
30988     _string_21_and_with/imm32/subx-name
30989     3/imm32/rm32-is-first-output
30990     1/imm32/r32-is-first-inout
30991     0/imm32/no-imm32
30992     0/imm32/no-imm8
30993     0/imm32/no-disp32
30994     0/imm32/no-xm32
30995     0/imm32/no-x32
30996     0x11/imm32/alloc-id:fake
30997     _Primitive-and-reg-with-mem/imm32/next
30998 _Primitive-and-reg-with-mem:  # (payload primitive)
30999     0x11/imm32/alloc-id:fake:payload
31000     # and-with var1 var2/reg => 21/and-with var1 var2/r32
31001     0x11/imm32/alloc-id:fake
31002     _string-and-with/imm32/name
31003     0x11/imm32/alloc-id:fake
31004     Two-args-int-stack-int-reg/imm32/inouts
31005     0/imm32/no-outputs
31006     0/imm32/no-outputs
31007     0x11/imm32/alloc-id:fake
31008     _string_21_and_with/imm32/subx-name
31009     1/imm32/rm32-is-first-inout
31010     2/imm32/r32-is-second-inout
31011     0/imm32/no-imm32
31012     0/imm32/no-imm8
31013     0/imm32/no-disp32
31014     0/imm32/no-xm32
31015     0/imm32/no-x32
31016     0x11/imm32/alloc-id:fake
31017     _Primitive-and-mem-with-reg/imm32/next
31018 _Primitive-and-mem-with-reg:  # (payload primitive)
31019     0x11/imm32/alloc-id:fake:payload
31020     # var1/reg <- and var2 => 23/and var2/rm32 var1/r32
31021     0x11/imm32/alloc-id:fake
31022     _string-and/imm32/name
31023     0x11/imm32/alloc-id:fake
31024     Single-int-var-in-mem/imm32/inouts
31025     0x11/imm32/alloc-id:fake
31026     Single-int-var-in-some-register/imm32/outputs
31027     0x11/imm32/alloc-id:fake
31028     _string_23_and/imm32/subx-name
31029     1/imm32/rm32-is-first-inout
31030     3/imm32/r32-is-first-output
31031     0/imm32/no-imm32
31032     0/imm32/no-imm8
31033     0/imm32/no-disp32
31034     0/imm32/no-xm32
31035     0/imm32/no-x32
31036     0x11/imm32/alloc-id:fake
31037     _Primitive-and-lit-with-reg/imm32/next
31038 _Primitive-and-lit-with-reg:  # (payload primitive)
31039     0x11/imm32/alloc-id:fake:payload
31040     # var1/reg <- and lit => 81 4/subop/and var1/rm32 lit/imm32
31041     0x11/imm32/alloc-id:fake
31042     _string-and/imm32/name
31043     0x11/imm32/alloc-id:fake
31044     Single-lit-var/imm32/inouts
31045     0x11/imm32/alloc-id:fake
31046     Single-int-var-in-some-register/imm32/outputs
31047     0x11/imm32/alloc-id:fake
31048     _string_81_subop_and/imm32/subx-name
31049     3/imm32/rm32-is-first-output
31050     0/imm32/no-r32
31051     1/imm32/imm32-is-first-inout
31052     0/imm32/no-imm8
31053     0/imm32/no-disp32
31054     0/imm32/no-xm32
31055     0/imm32/no-x32
31056     0x11/imm32/alloc-id:fake
31057     _Primitive-and-lit-with-mem/imm32/next
31058 _Primitive-and-lit-with-mem:  # (payload primitive)
31059     0x11/imm32/alloc-id:fake:payload
31060     # and-with var1, lit => 81 4/subop/and var1/rm32 lit/imm32
31061     0x11/imm32/alloc-id:fake
31062     _string-and-with/imm32/name
31063     0x11/imm32/alloc-id:fake
31064     Int-var-and-literal/imm32/inouts
31065     0/imm32/no-outputs
31066     0/imm32/no-outputs
31067     0x11/imm32/alloc-id:fake
31068     _string_81_subop_and/imm32/subx-name
31069     1/imm32/rm32-is-first-inout
31070     0/imm32/no-r32
31071     2/imm32/imm32-is-second-inout
31072     0/imm32/no-imm8
31073     0/imm32/no-disp32
31074     0/imm32/no-xm32
31075     0/imm32/no-x32
31076     0x11/imm32/alloc-id:fake
31077     _Primitive-or-with-eax/imm32/next
31078 # - or
31079 _Primitive-or-with-eax:  # (payload primitive)
31080     0x11/imm32/alloc-id:fake:payload
31081     # var/eax <- or lit => 0d/or-with-eax lit/imm32
31082     0x11/imm32/alloc-id:fake
31083     _string-or/imm32/name
31084     0x11/imm32/alloc-id:fake
31085     Single-lit-var/imm32/inouts
31086     0x11/imm32/alloc-id:fake
31087     Single-int-var-in-eax/imm32/outputs
31088     0x11/imm32/alloc-id:fake
31089     _string_0d_or_with_eax/imm32/subx-name
31090     0/imm32/no-rm32
31091     0/imm32/no-r32
31092     1/imm32/imm32-is-first-inout
31093     0/imm32/no-imm8
31094     0/imm32/no-disp32
31095     0/imm32/no-xm32
31096     0/imm32/no-x32
31097     0x11/imm32/alloc-id:fake
31098     _Primitive-or-reg-with-reg/imm32/next
31099 _Primitive-or-reg-with-reg:  # (payload primitive)
31100     0x11/imm32/alloc-id:fake:payload
31101     # var1/reg <- or var2/reg => 09/or-with var1/rm32 var2/r32
31102     0x11/imm32/alloc-id:fake
31103     _string-or/imm32/name
31104     0x11/imm32/alloc-id:fake
31105     Single-int-var-in-some-register/imm32/inouts
31106     0x11/imm32/alloc-id:fake
31107     Single-int-var-in-some-register/imm32/outputs
31108     0x11/imm32/alloc-id:fake
31109     _string_09_or_with/imm32/subx-name
31110     3/imm32/rm32-is-first-output
31111     1/imm32/r32-is-first-inout
31112     0/imm32/no-imm32
31113     0/imm32/no-imm8
31114     0/imm32/no-disp32
31115     0/imm32/no-xm32
31116     0/imm32/no-x32
31117     0x11/imm32/alloc-id:fake
31118     _Primitive-or-reg-with-mem/imm32/next
31119 _Primitive-or-reg-with-mem:  # (payload primitive)
31120     0x11/imm32/alloc-id:fake:payload
31121     # or-with var1 var2/reg => 09/or-with var1 var2/r32
31122     0x11/imm32/alloc-id:fake
31123     _string-or-with/imm32/name
31124     0x11/imm32/alloc-id:fake
31125     Two-args-int-stack-int-reg/imm32/inouts
31126     0/imm32/no-outputs
31127     0/imm32/no-outputs
31128     0x11/imm32/alloc-id:fake
31129     _string_09_or_with/imm32/subx-name
31130     1/imm32/rm32-is-first-inout
31131     2/imm32/r32-is-second-inout
31132     0/imm32/no-imm32
31133     0/imm32/no-imm8
31134     0/imm32/no-disp32
31135     0/imm32/no-xm32
31136     0/imm32/no-x32
31137     0x11/imm32/alloc-id:fake
31138     _Primitive-or-mem-with-reg/imm32/next
31139 _Primitive-or-mem-with-reg:  # (payload primitive)
31140     0x11/imm32/alloc-id:fake:payload
31141     # var1/reg <- or var2 => 0b/or var2/rm32 var1/r32
31142     0x11/imm32/alloc-id:fake
31143     _string-or/imm32/name
31144     0x11/imm32/alloc-id:fake
31145     Single-int-var-in-mem/imm32/inouts
31146     0x11/imm32/alloc-id:fake
31147     Single-int-var-in-some-register/imm32/outputs
31148     0x11/imm32/alloc-id:fake
31149     _string_0b_or/imm32/subx-name
31150     1/imm32/rm32-is-first-inout
31151     3/imm32/r32-is-first-output
31152     0/imm32/no-imm32
31153     0/imm32/no-imm8
31154     0/imm32/no-disp32
31155     0/imm32/no-xm32
31156     0/imm32/no-x32
31157     0x11/imm32/alloc-id:fake
31158     _Primitive-or-lit-with-reg/imm32/next
31159 _Primitive-or-lit-with-reg:  # (payload primitive)
31160     0x11/imm32/alloc-id:fake:payload
31161     # var1/reg <- or lit => 81 1/subop/or var1/rm32 lit/imm32
31162     0x11/imm32/alloc-id:fake
31163     _string-or/imm32/name
31164     0x11/imm32/alloc-id:fake
31165     Single-lit-var/imm32/inouts
31166     0x11/imm32/alloc-id:fake
31167     Single-int-var-in-some-register/imm32/outputs
31168     0x11/imm32/alloc-id:fake
31169     _string_81_subop_or/imm32/subx-name
31170     3/imm32/rm32-is-first-output
31171     0/imm32/no-r32
31172     1/imm32/imm32-is-first-inout
31173     0/imm32/no-imm8
31174     0/imm32/no-disp32
31175     0/imm32/no-xm32
31176     0/imm32/no-x32
31177     0x11/imm32/alloc-id:fake
31178     _Primitive-or-lit-with-mem/imm32/next
31179 _Primitive-or-lit-with-mem:  # (payload primitive)
31180     0x11/imm32/alloc-id:fake:payload
31181     # or-with var1, lit => 81 1/subop/or var1/rm32 lit/imm32
31182     0x11/imm32/alloc-id:fake
31183     _string-or-with/imm32/name
31184     0x11/imm32/alloc-id:fake
31185     Int-var-and-literal/imm32/inouts
31186     0/imm32/no-outputs
31187     0/imm32/no-outputs
31188     0x11/imm32/alloc-id:fake
31189     _string_81_subop_or/imm32/subx-name
31190     1/imm32/rm32-is-first-inout
31191     0/imm32/no-r32
31192     2/imm32/imm32-is-second-inout
31193     0/imm32/no-imm8
31194     0/imm32/no-disp32
31195     0/imm32/no-xm32
31196     0/imm32/no-x32
31197     0x11/imm32/alloc-id:fake
31198     _Primitive-xor-with-eax/imm32/next
31199 # - xor
31200 _Primitive-xor-with-eax:  # (payload primitive)
31201     0x11/imm32/alloc-id:fake:payload
31202     # var/eax <- xor lit => 35/xor-with-eax lit/imm32
31203     0x11/imm32/alloc-id:fake
31204     _string-xor/imm32/name
31205     0x11/imm32/alloc-id:fake
31206     Single-lit-var/imm32/inouts
31207     0x11/imm32/alloc-id:fake
31208     Single-int-var-in-eax/imm32/outputs
31209     0x11/imm32/alloc-id:fake
31210     _string_35_xor_with_eax/imm32/subx-name
31211     0/imm32/no-rm32
31212     0/imm32/no-r32
31213     1/imm32/imm32-is-first-inout
31214     0/imm32/no-imm8
31215     0/imm32/no-disp32
31216     0/imm32/no-xm32
31217     0/imm32/no-x32
31218     0x11/imm32/alloc-id:fake
31219     _Primitive-xor-reg-with-reg/imm32/next
31220 _Primitive-xor-reg-with-reg:  # (payload primitive)
31221     0x11/imm32/alloc-id:fake:payload
31222     # var1/reg <- xor var2/reg => 31/xor-with var1/rm32 var2/r32
31223     0x11/imm32/alloc-id:fake
31224     _string-xor/imm32/name
31225     0x11/imm32/alloc-id:fake
31226     Single-int-var-in-some-register/imm32/inouts
31227     0x11/imm32/alloc-id:fake
31228     Single-int-var-in-some-register/imm32/outputs
31229     0x11/imm32/alloc-id:fake
31230     _string_31_xor_with/imm32/subx-name
31231     3/imm32/rm32-is-first-output
31232     1/imm32/r32-is-first-inout
31233     0/imm32/no-imm32
31234     0/imm32/no-imm8
31235     0/imm32/no-disp32
31236     0/imm32/no-xm32
31237     0/imm32/no-x32
31238     0x11/imm32/alloc-id:fake
31239     _Primitive-xor-reg-with-mem/imm32/next
31240 _Primitive-xor-reg-with-mem:  # (payload primitive)
31241     0x11/imm32/alloc-id:fake:payload
31242     # xor-with var1 var2/reg => 31/xor-with var1 var2/r32
31243     0x11/imm32/alloc-id:fake
31244     _string-xor-with/imm32/name
31245     0x11/imm32/alloc-id:fake
31246     Two-args-int-stack-int-reg/imm32/inouts
31247     0/imm32/no-outputs
31248     0/imm32/no-outputs
31249     0x11/imm32/alloc-id:fake
31250     _string_31_xor_with/imm32/subx-name
31251     1/imm32/rm32-is-first-inout
31252     2/imm32/r32-is-second-inout
31253     0/imm32/no-imm32
31254     0/imm32/no-imm8
31255     0/imm32/no-disp32
31256     0/imm32/no-xm32
31257     0/imm32/no-x32
31258     0x11/imm32/alloc-id:fake
31259     _Primitive-xor-mem-with-reg/imm32/next
31260 _Primitive-xor-mem-with-reg:  # (payload primitive)
31261     0x11/imm32/alloc-id:fake:payload
31262     # var1/reg <- xor var2 => 33/xor var2/rm32 var1/r32
31263     0x11/imm32/alloc-id:fake
31264     _string-xor/imm32/name
31265     0x11/imm32/alloc-id:fake
31266     Single-int-var-in-mem/imm32/inouts
31267     0x11/imm32/alloc-id:fake
31268     Single-int-var-in-some-register/imm32/outputs
31269     0x11/imm32/alloc-id:fake
31270     _string_33_xor/imm32/subx-name
31271     1/imm32/rm32-is-first-inout
31272     3/imm32/r32-is-first-output
31273     0/imm32/no-imm32
31274     0/imm32/no-imm8
31275     0/imm32/no-disp32
31276     0/imm32/no-xm32
31277     0/imm32/no-x32
31278     0x11/imm32/alloc-id:fake
31279     _Primitive-xor-lit-with-reg/imm32/next
31280 _Primitive-xor-lit-with-reg:  # (payload primitive)
31281     0x11/imm32/alloc-id:fake:payload
31282     # var1/reg <- xor lit => 81 6/subop/xor var1/rm32 lit/imm32
31283     0x11/imm32/alloc-id:fake
31284     _string-xor/imm32/name
31285     0x11/imm32/alloc-id:fake
31286     Single-lit-var/imm32/inouts
31287     0x11/imm32/alloc-id:fake
31288     Single-int-var-in-some-register/imm32/outputs
31289     0x11/imm32/alloc-id:fake
31290     _string_81_subop_xor/imm32/subx-name
31291     3/imm32/rm32-is-first-output
31292     0/imm32/no-r32
31293     1/imm32/imm32-is-first-inout
31294     0/imm32/no-imm8
31295     0/imm32/no-disp32
31296     0/imm32/no-xm32
31297     0/imm32/no-x32
31298     0x11/imm32/alloc-id:fake
31299     _Primitive-xor-lit-with-mem/imm32/next
31300 _Primitive-xor-lit-with-mem:  # (payload primitive)
31301     0x11/imm32/alloc-id:fake:payload
31302     # xor-with var1, lit => 81 6/subop/xor var1/rm32 lit/imm32
31303     0x11/imm32/alloc-id:fake
31304     _string-xor-with/imm32/name
31305     0x11/imm32/alloc-id:fake
31306     Int-var-and-literal/imm32/inouts
31307     0/imm32/no-outputs
31308     0/imm32/no-outputs
31309     0x11/imm32/alloc-id:fake
31310     _string_81_subop_xor/imm32/subx-name
31311     1/imm32/rm32-is-first-inout
31312     0/imm32/no-r32
31313     2/imm32/imm32-is-second-inout
31314     0/imm32/no-imm8
31315     0/imm32/no-disp32
31316     0/imm32/no-xm32
31317     0/imm32/no-x32
31318     0x11/imm32/alloc-id:fake
31319     _Primitive-shift-reg-left-by-lit/imm32/next
31320 _Primitive-shift-reg-left-by-lit:  # (payload primitive)
31321     0x11/imm32/alloc-id:fake:payload
31322     # var1/reg <- shift-left lit => c1/shift 4/subop/left var1/rm32 lit/imm32
31323     0x11/imm32/alloc-id:fake
31324     _string-shift-left/imm32/name
31325     0x11/imm32/alloc-id:fake
31326     Single-lit-var/imm32/inouts
31327     0x11/imm32/alloc-id:fake
31328     Single-int-var-in-some-register/imm32/outputs
31329     0x11/imm32/alloc-id:fake
31330     _string_c1_subop_shift_left/imm32/subx-name
31331     3/imm32/rm32-is-first-output
31332     0/imm32/no-r32
31333     0/imm32/no-imm32
31334     1/imm32/imm8-is-first-inout
31335     0/imm32/no-disp32
31336     0/imm32/no-xm32
31337     0/imm32/no-x32
31338     0x11/imm32/alloc-id:fake
31339     _Primitive-shift-reg-right-by-lit/imm32/next
31340 _Primitive-shift-reg-right-by-lit:  # (payload primitive)
31341     0x11/imm32/alloc-id:fake:payload
31342     # var1/reg <- shift-right lit => c1/shift 5/subop/right var1/rm32 lit/imm32
31343     0x11/imm32/alloc-id:fake
31344     _string-shift-right/imm32/name
31345     0x11/imm32/alloc-id:fake
31346     Single-lit-var/imm32/inouts
31347     0x11/imm32/alloc-id:fake
31348     Single-int-var-in-some-register/imm32/outputs
31349     0x11/imm32/alloc-id:fake
31350     _string_c1_subop_shift_right_padding_zeroes/imm32/subx-name
31351     3/imm32/rm32-is-first-output
31352     0/imm32/no-r32
31353     0/imm32/no-imm32
31354     1/imm32/imm8-is-first-inout
31355     0/imm32/no-disp32
31356     0/imm32/no-xm32
31357     0/imm32/no-x32
31358     0x11/imm32/alloc-id:fake
31359     _Primitive-shift-reg-right-signed-by-lit/imm32/next
31360 _Primitive-shift-reg-right-signed-by-lit:  # (payload primitive)
31361     0x11/imm32/alloc-id:fake:payload
31362     # var1/reg <- shift-right-signed lit => c1/shift 7/subop/right-preserving-sign var1/rm32 lit/imm32
31363     0x11/imm32/alloc-id:fake
31364     _string-shift-right-signed/imm32/name
31365     0x11/imm32/alloc-id:fake
31366     Single-lit-var/imm32/inouts
31367     0x11/imm32/alloc-id:fake
31368     Single-int-var-in-some-register/imm32/outputs
31369     0x11/imm32/alloc-id:fake
31370     _string_c1_subop_shift_right_preserving_sign/imm32/subx-name
31371     3/imm32/rm32-is-first-output
31372     0/imm32/no-r32
31373     0/imm32/no-imm32
31374     1/imm32/imm8-is-first-inout
31375     0/imm32/no-disp32
31376     0/imm32/no-xm32
31377     0/imm32/no-x32
31378     0x11/imm32/alloc-id:fake
31379     _Primitive-shift-mem-left-by-lit/imm32/next
31380 _Primitive-shift-mem-left-by-lit:  # (payload primitive)
31381     0x11/imm32/alloc-id:fake:payload
31382     # shift-left var1, lit => c1/shift 4/subop/left var1/rm32 lit/imm32
31383     0x11/imm32/alloc-id:fake
31384     _string-shift-left/imm32/name
31385     0x11/imm32/alloc-id:fake
31386     Int-var-and-literal/imm32/inouts
31387     0/imm32/no-outputs
31388     0/imm32/no-outputs
31389     0x11/imm32/alloc-id:fake
31390     _string_c1_subop_shift_left/imm32/subx-name
31391     1/imm32/rm32-is-first-inout
31392     0/imm32/no-r32
31393     0/imm32/no-imm32
31394     2/imm32/imm8-is-second-inout
31395     0/imm32/no-disp32
31396     0/imm32/no-xm32
31397     0/imm32/no-x32
31398     0x11/imm32/alloc-id:fake
31399     _Primitive-shift-mem-right-by-lit/imm32/next
31400 _Primitive-shift-mem-right-by-lit:  # (payload primitive)
31401     0x11/imm32/alloc-id:fake:payload
31402     # shift-right var1, lit => c1/shift 5/subop/right var1/rm32 lit/imm32
31403     0x11/imm32/alloc-id:fake
31404     _string-shift-right/imm32/name
31405     0x11/imm32/alloc-id:fake
31406     Int-var-and-literal/imm32/inouts
31407     0/imm32/no-outputs
31408     0/imm32/no-outputs
31409     0x11/imm32/alloc-id:fake
31410     _string_c1_subop_shift_right_padding_zeroes/imm32/subx-name
31411     1/imm32/rm32-is-first-inout
31412     0/imm32/no-r32
31413     0/imm32/no-imm32
31414     2/imm32/imm8-is-second-inout
31415     0/imm32/no-disp32
31416     0/imm32/no-xm32
31417     0/imm32/no-x32
31418     0x11/imm32/alloc-id:fake
31419     _Primitive-shift-mem-right-signed-by-lit/imm32/next
31420 _Primitive-shift-mem-right-signed-by-lit:  # (payload primitive)
31421     0x11/imm32/alloc-id:fake:payload
31422     # shift-right-signed var1, lit => c1/shift 7/subop/right-preserving-sign var1/rm32 lit/imm32
31423     0x11/imm32/alloc-id:fake
31424     _string-shift-right-signed/imm32/name
31425     0x11/imm32/alloc-id:fake
31426     Int-var-and-literal/imm32/inouts
31427     0/imm32/no-outputs
31428     0/imm32/no-outputs
31429     0x11/imm32/alloc-id:fake
31430     _string_c1_subop_shift_right_preserving_sign/imm32/subx-name
31431     1/imm32/rm32-is-first-inout
31432     0/imm32/no-r32
31433     0/imm32/no-imm32
31434     2/imm32/imm8-is-second-inout
31435     0/imm32/no-disp32
31436     0/imm32/no-xm32
31437     0/imm32/no-x32
31438     0x11/imm32/alloc-id:fake
31439     _Primitive-copy-to-eax/imm32/next
31440 # - copy
31441 _Primitive-copy-to-eax:  # (payload primitive)
31442     0x11/imm32/alloc-id:fake:payload
31443     # var/eax <- copy lit => b8/copy-to-eax lit/imm32
31444     0x11/imm32/alloc-id:fake
31445     _string-copy/imm32/name
31446     0x11/imm32/alloc-id:fake
31447     Single-lit-var/imm32/inouts
31448     0x11/imm32/alloc-id:fake
31449     Single-int-var-in-eax/imm32/outputs
31450     0x11/imm32/alloc-id:fake
31451     _string_b8_copy_to_eax/imm32/subx-name
31452     0/imm32/no-rm32
31453     0/imm32/no-r32
31454     1/imm32/imm32-is-first-inout
31455     0/imm32/no-imm8
31456     0/imm32/no-disp32
31457     0/imm32/no-xm32
31458     0/imm32/no-x32
31459     0x11/imm32/alloc-id:fake
31460     _Primitive-copy-to-ecx/imm32/next
31461 _Primitive-copy-to-ecx:  # (payload primitive)
31462     0x11/imm32/alloc-id:fake:payload
31463     # var/ecx <- copy lit => b9/copy-to-ecx lit/imm32
31464     0x11/imm32/alloc-id:fake
31465     _string-copy/imm32/name
31466     0x11/imm32/alloc-id:fake
31467     Single-lit-var/imm32/inouts
31468     0x11/imm32/alloc-id:fake
31469     Single-int-var-in-ecx/imm32/outputs
31470     0x11/imm32/alloc-id:fake
31471     _string_b9_copy_to_ecx/imm32/subx-name
31472     0/imm32/no-rm32
31473     0/imm32/no-r32
31474     1/imm32/imm32-is-first-inout
31475     0/imm32/no-imm8
31476     0/imm32/no-disp32
31477     0/imm32/no-xm32
31478     0/imm32/no-x32
31479     0x11/imm32/alloc-id:fake
31480     _Primitive-copy-to-edx/imm32/next
31481 _Primitive-copy-to-edx:  # (payload primitive)
31482     0x11/imm32/alloc-id:fake:payload
31483     # var/edx <- copy lit => ba/copy-to-edx lit/imm32
31484     0x11/imm32/alloc-id:fake
31485     _string-copy/imm32/name
31486     0x11/imm32/alloc-id:fake
31487     Single-lit-var/imm32/inouts
31488     0x11/imm32/alloc-id:fake
31489     Single-int-var-in-edx/imm32/outputs
31490     0x11/imm32/alloc-id:fake
31491     _string_ba_copy_to_edx/imm32/subx-name
31492     0/imm32/no-rm32
31493     0/imm32/no-r32
31494     1/imm32/imm32-is-first-inout
31495     0/imm32/no-imm8
31496     0/imm32/no-disp32
31497     0/imm32/no-xm32
31498     0/imm32/no-x32
31499     0x11/imm32/alloc-id:fake
31500     _Primitive-copy-to-ebx/imm32/next
31501 _Primitive-copy-to-ebx:  # (payload primitive)
31502     0x11/imm32/alloc-id:fake:payload
31503     # var/ebx <- copy lit => bb/copy-to-ebx lit/imm32
31504     0x11/imm32/alloc-id:fake
31505     _string-copy/imm32/name
31506     0x11/imm32/alloc-id:fake
31507     Single-lit-var/imm32/inouts
31508     0x11/imm32/alloc-id:fake
31509     Single-int-var-in-ebx/imm32/outputs
31510     0x11/imm32/alloc-id:fake
31511     _string_bb_copy_to_ebx/imm32/subx-name
31512     0/imm32/no-rm32
31513     0/imm32/no-r32
31514     1/imm32/imm32-is-first-inout
31515     0/imm32/no-imm8
31516     0/imm32/no-disp32
31517     0/imm32/no-xm32
31518     0/imm32/no-x32
31519     0x11/imm32/alloc-id:fake
31520     _Primitive-copy-to-esi/imm32/next
31521 _Primitive-copy-to-esi:  # (payload primitive)
31522     0x11/imm32/alloc-id:fake:payload
31523     # var/esi <- copy lit => be/copy-to-esi lit/imm32
31524     0x11/imm32/alloc-id:fake
31525     _string-copy/imm32/name
31526     0x11/imm32/alloc-id:fake
31527     Single-lit-var/imm32/inouts
31528     0x11/imm32/alloc-id:fake
31529     Single-int-var-in-esi/imm32/outputs
31530     0x11/imm32/alloc-id:fake
31531     _string_be_copy_to_esi/imm32/subx-name
31532     0/imm32/no-rm32
31533     0/imm32/no-r32
31534     1/imm32/imm32-is-first-inout
31535     0/imm32/no-imm8
31536     0/imm32/no-disp32
31537     0/imm32/no-xm32
31538     0/imm32/no-x32
31539     0x11/imm32/alloc-id:fake
31540     _Primitive-copy-to-edi/imm32/next
31541 _Primitive-copy-to-edi:  # (payload primitive)
31542     0x11/imm32/alloc-id:fake:payload
31543     # var/edi <- copy lit => bf/copy-to-edi lit/imm32
31544     0x11/imm32/alloc-id:fake
31545     _string-copy/imm32/name
31546     0x11/imm32/alloc-id:fake
31547     Single-lit-var/imm32/inouts
31548     0x11/imm32/alloc-id:fake
31549     Single-int-var-in-edi/imm32/outputs
31550     0x11/imm32/alloc-id:fake
31551     _string_bf_copy_to_edi/imm32/subx-name
31552     0/imm32/no-rm32
31553     0/imm32/no-r32
31554     1/imm32/imm32-is-first-inout
31555     0/imm32/no-imm8
31556     0/imm32/no-disp32
31557     0/imm32/no-xm32
31558     0/imm32/no-x32
31559     0x11/imm32/alloc-id:fake
31560     _Primitive-copy-reg-to-reg/imm32/next
31561 _Primitive-copy-reg-to-reg:  # (payload primitive)
31562     0x11/imm32/alloc-id:fake:payload
31563     # var1/reg <- copy var2/reg => 89/<- var1/rm32 var2/r32
31564     0x11/imm32/alloc-id:fake
31565     _string-copy/imm32/name
31566     0x11/imm32/alloc-id:fake
31567     Single-int-var-in-some-register/imm32/inouts
31568     0x11/imm32/alloc-id:fake
31569     Single-int-var-in-some-register/imm32/outputs
31570     0x11/imm32/alloc-id:fake
31571     _string_89_<-/imm32/subx-name
31572     3/imm32/rm32-is-first-output
31573     1/imm32/r32-is-first-inout
31574     0/imm32/no-imm32
31575     0/imm32/no-imm8
31576     0/imm32/no-disp32
31577     0/imm32/no-xm32
31578     0/imm32/no-x32
31579     0x11/imm32/alloc-id:fake
31580     _Primitive-copy-reg-to-mem/imm32/next
31581 _Primitive-copy-reg-to-mem:  # (payload primitive)
31582     0x11/imm32/alloc-id:fake:payload
31583     # copy-to var1 var2/reg => 89/<- var1 var2/r32
31584     0x11/imm32/alloc-id:fake
31585     _string-copy-to/imm32/name
31586     0x11/imm32/alloc-id:fake
31587     Two-args-int-stack-int-reg/imm32/inouts
31588     0/imm32/no-outputs
31589     0/imm32/no-outputs
31590     0x11/imm32/alloc-id:fake
31591     _string_89_<-/imm32/subx-name
31592     1/imm32/rm32-is-first-inout
31593     2/imm32/r32-is-second-inout
31594     0/imm32/no-imm32
31595     0/imm32/no-imm8
31596     0/imm32/no-disp32
31597     0/imm32/no-xm32
31598     0/imm32/no-x32
31599     0x11/imm32/alloc-id:fake
31600     _Primitive-copy-mem-to-reg/imm32/next
31601 _Primitive-copy-mem-to-reg:  # (payload primitive)
31602     0x11/imm32/alloc-id:fake:payload
31603     # var1/reg <- copy var2 => 8b/-> var2/rm32 var1/r32
31604     0x11/imm32/alloc-id:fake
31605     _string-copy/imm32/name
31606     0x11/imm32/alloc-id:fake
31607     Single-int-var-in-mem/imm32/inouts
31608     0x11/imm32/alloc-id:fake
31609     Single-int-var-in-some-register/imm32/outputs
31610     0x11/imm32/alloc-id:fake
31611     _string_8b_->/imm32/subx-name
31612     1/imm32/rm32-is-first-inout
31613     3/imm32/r32-is-first-output
31614     0/imm32/no-imm32
31615     0/imm32/no-imm8
31616     0/imm32/no-disp32
31617     0/imm32/no-xm32
31618     0/imm32/no-x32
31619     0x11/imm32/alloc-id:fake
31620     _Primitive-copy-lit-to-reg/imm32/next
31621 _Primitive-copy-lit-to-reg:  # (payload primitive)
31622     0x11/imm32/alloc-id:fake:payload
31623     # var1/reg <- copy lit => c7 0/subop/copy var1/rm32 lit/imm32
31624     0x11/imm32/alloc-id:fake
31625     _string-copy/imm32/name
31626     0x11/imm32/alloc-id:fake
31627     Single-lit-var/imm32/inouts
31628     0x11/imm32/alloc-id:fake
31629     Single-int-var-in-some-register/imm32/outputs
31630     0x11/imm32/alloc-id:fake
31631     _string_c7_subop_copy/imm32/subx-name
31632     3/imm32/rm32-is-first-output
31633     0/imm32/no-r32
31634     1/imm32/imm32-is-first-inout
31635     0/imm32/no-imm8
31636     0/imm32/no-disp32
31637     0/imm32/no-xm32
31638     0/imm32/no-x32
31639     0x11/imm32/alloc-id:fake
31640     _Primitive-copy-lit-to-mem/imm32/next
31641 _Primitive-copy-lit-to-mem:  # (payload primitive)
31642     0x11/imm32/alloc-id:fake:payload
31643     # copy-to var1, lit => c7 0/subop/copy var1/rm32 lit/imm32
31644     0x11/imm32/alloc-id:fake
31645     _string-copy-to/imm32/name
31646     0x11/imm32/alloc-id:fake
31647     Int-var-and-literal/imm32/inouts
31648     0/imm32/no-outputs
31649     0/imm32/no-outputs
31650     0x11/imm32/alloc-id:fake
31651     _string_c7_subop_copy/imm32/subx-name
31652     1/imm32/rm32-is-first-inout
31653     0/imm32/no-r32
31654     2/imm32/imm32-is-second-inout
31655     0/imm32/no-imm8
31656     0/imm32/no-disp32
31657     0/imm32/no-xm32
31658     0/imm32/no-x32
31659     0x11/imm32/alloc-id:fake
31660     _Primitive-copy-byte-from-reg/imm32/next
31661 # - copy byte
31662 _Primitive-copy-byte-from-reg:
31663     0x11/imm32/alloc-id:fake:payload
31664     # var/reg <- copy-byte var2/reg2 => 8a/byte-> %var2 var/r32
31665     0x11/imm32/alloc-id:fake
31666     _string-copy-byte/imm32/name
31667     0x11/imm32/alloc-id:fake
31668     Single-byte-var-in-some-register/imm32/inouts
31669     0x11/imm32/alloc-id:fake
31670     Single-byte-var-in-some-register/imm32/outputs
31671     0x11/imm32/alloc-id:fake
31672     _string_8a_copy_byte/imm32/subx-name
31673     1/imm32/rm32-is-first-inout
31674     3/imm32/r32-is-first-output
31675     0/imm32/no-imm32
31676     0/imm32/no-imm8
31677     0/imm32/no-disp32
31678     0/imm32/no-xm32
31679     0/imm32/no-x32
31680     0x11/imm32/alloc-id:fake
31681     _Primitive-copy-byte-from-mem/imm32/next
31682 _Primitive-copy-byte-from-mem:
31683     0x11/imm32/alloc-id:fake:payload
31684     # var/reg <- copy-byte *var2/reg2 => 8a/byte-> *var2 var/r32
31685     0x11/imm32/alloc-id:fake
31686     _string-copy-byte/imm32/name
31687     0x11/imm32/alloc-id:fake
31688     Single-byte-var-in-mem/imm32/inouts
31689     0x11/imm32/alloc-id:fake
31690     Single-byte-var-in-some-register/imm32/outputs
31691     0x11/imm32/alloc-id:fake
31692     _string_8a_copy_byte/imm32/subx-name
31693     1/imm32/rm32-is-first-inout
31694     3/imm32/r32-is-first-output
31695     0/imm32/no-imm32
31696     0/imm32/no-imm8
31697     0/imm32/no-disp32
31698     0/imm32/no-xm32
31699     0/imm32/no-x32
31700     0x11/imm32/alloc-id:fake
31701     _Primitive-copy-byte-to-mem/imm32/next
31702 _Primitive-copy-byte-to-mem:
31703     0x11/imm32/alloc-id:fake:payload
31704     # copy-byte-to *var1/reg1, var2/reg2 => 88/byte<- *reg1 reg2/r32
31705     0x11/imm32/alloc-id:fake
31706     _string-copy-byte-to/imm32/name
31707     0x11/imm32/alloc-id:fake
31708     Two-args-byte-stack-byte-reg/imm32/inouts
31709     0/imm32/no-outputs
31710     0/imm32/no-outputs
31711     0x11/imm32/alloc-id:fake
31712     _string_88_copy_byte/imm32/subx-name
31713     1/imm32/rm32-is-first-inout
31714     2/imm32/r32-is-second-inout
31715     0/imm32/no-imm32
31716     0/imm32/no-imm8
31717     0/imm32/no-disp32
31718     0/imm32/no-xm32
31719     0/imm32/no-x32
31720     0x11/imm32/alloc-id:fake
31721     _Primitive-address/imm32/next
31722 # - address
31723 _Primitive-address:  # (payload primitive)
31724     0x11/imm32/alloc-id:fake:payload
31725     # var1/reg <- address var2 => 8d/copy-address var2/rm32 var1/r32
31726     0x11/imm32/alloc-id:fake
31727     _string-address/imm32/name
31728     0x11/imm32/alloc-id:fake
31729     Single-int-var-in-mem/imm32/inouts
31730     0x11/imm32/alloc-id:fake
31731     Single-addr-var-in-some-register/imm32/outputs
31732     0x11/imm32/alloc-id:fake
31733     _string_8d_copy_address/imm32/subx-name
31734     1/imm32/rm32-is-first-inout
31735     3/imm32/r32-is-first-output
31736     0/imm32/no-imm32
31737     0/imm32/no-imm8
31738     0/imm32/no-disp32
31739     0/imm32/no-xm32
31740     0/imm32/no-x32
31741     0x11/imm32/alloc-id:fake
31742     _Primitive-compare-reg-with-reg/imm32/next
31743 # - compare
31744 _Primitive-compare-reg-with-reg:  # (payload primitive)
31745     0x11/imm32/alloc-id:fake:payload
31746     # compare var1/reg1 var2/reg2 => 39/compare var1/rm32 var2/r32
31747     0x11/imm32/alloc-id:fake
31748     _string-compare/imm32/name
31749     0x11/imm32/alloc-id:fake
31750     Two-int-args-in-regs/imm32/inouts
31751     0/imm32/no-outputs
31752     0/imm32/no-outputs
31753     0x11/imm32/alloc-id:fake
31754     _string_39_compare->/imm32/subx-name
31755     1/imm32/rm32-is-first-inout
31756     2/imm32/r32-is-second-inout
31757     0/imm32/no-imm32
31758     0/imm32/no-imm8
31759     0/imm32/no-disp32
31760     0/imm32/no-xm32
31761     0/imm32/no-x32
31762     0x11/imm32/alloc-id:fake
31763     _Primitive-compare-mem-with-reg/imm32/next
31764 _Primitive-compare-mem-with-reg:  # (payload primitive)
31765     0x11/imm32/alloc-id:fake:payload
31766     # compare var1 var2/reg => 39/compare var1/rm32 var2/r32
31767     0x11/imm32/alloc-id:fake
31768     _string-compare/imm32/name
31769     0x11/imm32/alloc-id:fake
31770     Two-args-int-stack-int-reg/imm32/inouts
31771     0/imm32/no-outputs
31772     0/imm32/no-outputs
31773     0x11/imm32/alloc-id:fake
31774     _string_39_compare->/imm32/subx-name
31775     1/imm32/rm32-is-first-inout
31776     2/imm32/r32-is-second-inout
31777     0/imm32/no-imm32
31778     0/imm32/no-imm8
31779     0/imm32/no-disp32
31780     0/imm32/no-xm32
31781     0/imm32/no-x32
31782     0x11/imm32/alloc-id:fake
31783     _Primitive-compare-reg-with-mem/imm32/next
31784 _Primitive-compare-reg-with-mem:  # (payload primitive)
31785     0x11/imm32/alloc-id:fake:payload
31786     # compare var1/reg var2 => 3b/compare<- var2/rm32 var1/r32
31787     0x11/imm32/alloc-id:fake
31788     _string-compare/imm32/name
31789     0x11/imm32/alloc-id:fake
31790     Two-args-int-reg-int-stack/imm32/inouts
31791     0/imm32/no-outputs
31792     0/imm32/no-outputs
31793     0x11/imm32/alloc-id:fake
31794     _string_3b_compare<-/imm32/subx-name
31795     2/imm32/rm32-is-second-inout
31796     1/imm32/r32-is-first-inout
31797     0/imm32/no-imm32
31798     0/imm32/no-imm8
31799     0/imm32/no-disp32
31800     0/imm32/no-xm32
31801     0/imm32/no-x32
31802     0x11/imm32/alloc-id:fake
31803     _Primitive-compare-eax-with-literal/imm32/next
31804 _Primitive-compare-eax-with-literal:  # (payload primitive)
31805     0x11/imm32/alloc-id:fake:payload
31806     # compare var1/eax n => 3d/compare-eax-with n/imm32
31807     0x11/imm32/alloc-id:fake
31808     _string-compare/imm32/name
31809     0x11/imm32/alloc-id:fake
31810     Two-args-int-eax-int-literal/imm32/inouts
31811     0/imm32/no-outputs
31812     0/imm32/no-outputs
31813     0x11/imm32/alloc-id:fake
31814     _string_3d_compare_eax_with/imm32/subx-name
31815     0/imm32/no-rm32
31816     0/imm32/no-r32
31817     2/imm32/imm32-is-second-inout
31818     0/imm32/no-imm8
31819     0/imm32/no-disp32
31820     0/imm32/no-xm32
31821     0/imm32/no-x32
31822     0x11/imm32/alloc-id:fake
31823     _Primitive-compare-reg-with-literal/imm32/next
31824 _Primitive-compare-reg-with-literal:  # (payload primitive)
31825     0x11/imm32/alloc-id:fake:payload
31826     # compare var1/reg n => 81 7/subop/compare %reg n/imm32
31827     0x11/imm32/alloc-id:fake
31828     _string-compare/imm32/name
31829     0x11/imm32/alloc-id:fake
31830     Int-var-in-register-and-literal/imm32/inouts
31831     0/imm32/no-outputs
31832     0/imm32/no-outputs
31833     0x11/imm32/alloc-id:fake
31834     _string_81_subop_compare/imm32/subx-name
31835     1/imm32/rm32-is-first-inout
31836     0/imm32/no-r32
31837     2/imm32/imm32-is-second-inout
31838     0/imm32/no-imm8
31839     0/imm32/no-disp32
31840     0/imm32/no-xm32
31841     0/imm32/no-x32
31842     0x11/imm32/alloc-id:fake
31843     _Primitive-compare-mem-with-literal/imm32/next
31844 _Primitive-compare-mem-with-literal:  # (payload primitive)
31845     0x11/imm32/alloc-id:fake:payload
31846     # compare var1 n => 81 7/subop/compare *(ebp+___) n/imm32
31847     0x11/imm32/alloc-id:fake
31848     _string-compare/imm32/name
31849     0x11/imm32/alloc-id:fake
31850     Int-var-and-literal/imm32/inouts
31851     0/imm32/no-outputs
31852     0/imm32/no-outputs
31853     0x11/imm32/alloc-id:fake
31854     _string_81_subop_compare/imm32/subx-name
31855     1/imm32/rm32-is-first-inout
31856     0/imm32/no-r32
31857     2/imm32/imm32-is-second-inout
31858     0/imm32/no-imm8
31859     0/imm32/no-disp32
31860     0/imm32/no-xm32
31861     0/imm32/no-x32
31862     0x11/imm32/alloc-id:fake
31863     _Primitive-negate-reg/imm32/next
31864 # - negate
31865 _Primitive-negate-reg:  # (payload primitive)
31866     0x11/imm32/alloc-id:fake:payload
31867     # var1/reg <- negate => f7 3/subop/negate var1/rm32
31868     0x11/imm32/alloc-id:fake
31869     _string-negate/imm32/name
31870     0/imm32/no-inouts
31871     0/imm32/no-inouts
31872     0x11/imm32/alloc-id:fake
31873     Single-int-var-in-some-register/imm32/outputs
31874     0x11/imm32/alloc-id:fake
31875     _string_f7_subop_negate/imm32/subx-name
31876     3/imm32/rm32-is-first-output
31877     0/imm32/no-r32
31878     0/imm32/no-imm32
31879     0/imm32/no-imm8
31880     0/imm32/no-disp32
31881     0/imm32/no-xm32
31882     0/imm32/no-x32
31883     0x11/imm32/alloc-id:fake
31884     _Primitive-negate-mem/imm32/next
31885 _Primitive-negate-mem:  # (payload primitive)
31886     0x11/imm32/alloc-id:fake:payload
31887     # negate var1 => f7 3/subop/negate var1/rm32
31888     0x11/imm32/alloc-id:fake
31889     _string-negate/imm32/name
31890     0x11/imm32/alloc-id:fake
31891     Single-int-var-in-mem/imm32/inouts
31892     0/imm32/no-outputs
31893     0/imm32/no-outputs
31894     0x11/imm32/alloc-id:fake
31895     _string_f7_subop_negate/imm32/subx-name
31896     1/imm32/rm32-is-first-inout
31897     0/imm32/no-r32
31898     0/imm32/no-imm32
31899     0/imm32/no-imm8
31900     0/imm32/no-disp32
31901     0/imm32/no-xm32
31902     0/imm32/no-x32
31903     0x11/imm32/alloc-id:fake
31904     _Primitive-multiply-reg-by-reg/imm32/next
31905 # - multiply
31906 _Primitive-multiply-reg-by-reg:  # (payload primitive)
31907     0x11/imm32/alloc-id:fake:payload
31908     # var1/reg <- multiply var2 => 0f af/multiply var2/rm32 var1/r32
31909     0x11/imm32/alloc-id:fake
31910     _string-multiply/imm32/name
31911     0x11/imm32/alloc-id:fake
31912     Single-int-var-in-some-register/imm32/inouts
31913     0x11/imm32/alloc-id:fake
31914     Single-int-var-in-some-register/imm32/outputs
31915     0x11/imm32/alloc-id:fake
31916     _string_0f_af_multiply/imm32/subx-name
31917     1/imm32/rm32-is-first-inout
31918     3/imm32/r32-is-first-output
31919     0/imm32/no-imm32
31920     0/imm32/no-imm8
31921     0/imm32/no-disp32
31922     0/imm32/no-xm32
31923     0/imm32/no-x32
31924     0x11/imm32/alloc-id:fake
31925     _Primitive-multiply-reg-by-mem/imm32/next
31926 _Primitive-multiply-reg-by-mem:  # (payload primitive)
31927     0x11/imm32/alloc-id:fake:payload
31928     # var1/reg <- multiply var2 => 0f af/multiply var2/rm32 var1/r32
31929     0x11/imm32/alloc-id:fake
31930     _string-multiply/imm32/name
31931     0x11/imm32/alloc-id:fake
31932     Single-int-var-in-mem/imm32/inouts
31933     0x11/imm32/alloc-id:fake
31934     Single-int-var-in-some-register/imm32/outputs
31935     0x11/imm32/alloc-id:fake
31936     _string_0f_af_multiply/imm32/subx-name
31937     1/imm32/rm32-is-first-inout
31938     3/imm32/r32-is-first-output
31939     0/imm32/no-imm32
31940     0/imm32/no-imm8
31941     0/imm32/no-disp32
31942     0/imm32/no-xm32
31943     0/imm32/no-x32
31944     0x11/imm32/alloc-id:fake
31945     _Primitive-convert-mem-to-xreg/imm32/next
31946 # - convert int to floating point
31947 _Primitive-convert-mem-to-xreg:  # (payload primitive)
31948     0x11/imm32/alloc-id:fake:payload
31949     # var1/xreg <- convert var2 => f3 0f 2a/convert-to-float var2/rm32 var1/x32
31950     0x11/imm32/alloc-id:fake
31951     _string-convert/imm32/name
31952     0x11/imm32/alloc-id:fake
31953     Single-int-var-in-mem/imm32/inouts
31954     0x11/imm32/alloc-id:fake
31955     Single-float-var-in-some-register/imm32/outputs
31956     0x11/imm32/alloc-id:fake
31957     _string_f3_0f_2a_convert_to_float/imm32/subx-name
31958     1/imm32/rm32-is-first-inout
31959     0/imm32/no-r32
31960     0/imm32/no-imm32
31961     0/imm32/no-imm8
31962     0/imm32/no-disp32
31963     0/imm32/no-xm32
31964     3/imm32/x32-is-first-output
31965     0x11/imm32/alloc-id:fake
31966     _Primitive-convert-reg-to-xreg/imm32/next
31967 _Primitive-convert-reg-to-xreg:  # (payload primitive)
31968     0x11/imm32/alloc-id:fake:payload
31969     # var1/xreg <- convert var2/reg => f3 0f 2a/convert-to-float var2/rm32 var1/x32
31970     0x11/imm32/alloc-id:fake
31971     _string-convert/imm32/name
31972     0x11/imm32/alloc-id:fake
31973     Single-int-var-in-some-register/imm32/inouts
31974     0x11/imm32/alloc-id:fake
31975     Single-float-var-in-some-register/imm32/outputs
31976     0x11/imm32/alloc-id:fake
31977     _string_f3_0f_2a_convert_to_float/imm32/subx-name
31978     1/imm32/rm32-is-first-inout
31979     0/imm32/no-r32
31980     0/imm32/no-imm32
31981     0/imm32/no-imm8
31982     0/imm32/no-disp32
31983     0/imm32/no-xm32
31984     3/imm32/x32-is-first-output
31985     0x11/imm32/alloc-id:fake
31986     _Primitive-convert-xmem-to-reg/imm32/next
31987 # - convert floating point to int
31988 _Primitive-convert-xmem-to-reg:  # (payload primitive)
31989     0x11/imm32/alloc-id:fake:payload
31990     # var1/reg <- convert var2 => f3 0f 2d/convert-to-int var2/xm32 var1/r32
31991     0x11/imm32/alloc-id:fake
31992     _string-convert/imm32/name
31993     0x11/imm32/alloc-id:fake
31994     Single-float-var-in-mem/imm32/inouts
31995     0x11/imm32/alloc-id:fake
31996     Single-int-var-in-some-register/imm32/outputs
31997     0x11/imm32/alloc-id:fake
31998     _string_f3_0f_2d_convert_to_int/imm32/subx-name
31999     0/imm32/no-rm32
32000     3/imm32/r32-is-first-output
32001     0/imm32/no-imm32
32002     0/imm32/no-imm8
32003     0/imm32/no-disp32
32004     1/imm32/xm32-is-first-inout
32005     0/imm32/no-x32
32006     0x11/imm32/alloc-id:fake
32007     _Primitive-convert-xreg-to-reg/imm32/next
32008 _Primitive-convert-xreg-to-reg:  # (payload primitive)
32009     0x11/imm32/alloc-id:fake:payload
32010     # var1/reg <- convert var2/xreg => f3 0f 2d/convert-to-int var2/xm32 var1/r32
32011     0x11/imm32/alloc-id:fake
32012     _string-convert/imm32/name
32013     0x11/imm32/alloc-id:fake
32014     Single-float-var-in-some-register/imm32/inouts
32015     0x11/imm32/alloc-id:fake
32016     Single-int-var-in-some-register/imm32/outputs
32017     0x11/imm32/alloc-id:fake
32018     _string_f3_0f_2d_convert_to_int/imm32/subx-name
32019     0/imm32/no-rm32
32020     3/imm32/r32-is-first-output
32021     0/imm32/no-imm32
32022     0/imm32/no-imm8
32023     0/imm32/no-disp32
32024     1/imm32/xm32-is-first-inout
32025     0/imm32/no-x32
32026     0x11/imm32/alloc-id:fake
32027     _Primitive-truncate-xmem-to-reg/imm32/next
32028 _Primitive-truncate-xmem-to-reg:  # (payload primitive)
32029     0x11/imm32/alloc-id:fake:payload
32030     # var1/reg <- truncate var2 => f3 0f 2c/truncate-to-int var2/xm32 var1/r32
32031     0x11/imm32/alloc-id:fake
32032     _string-truncate/imm32/name
32033     0x11/imm32/alloc-id:fake
32034     Single-float-var-in-mem/imm32/inouts
32035     0x11/imm32/alloc-id:fake
32036     Single-int-var-in-some-register/imm32/outputs
32037     0x11/imm32/alloc-id:fake
32038     _string_f3_0f_2c_truncate_to_int/imm32/subx-name
32039     0/imm32/no-rm32
32040     3/imm32/r32-is-first-output
32041     0/imm32/no-imm32
32042     0/imm32/no-imm8
32043     0/imm32/no-disp32
32044     1/imm32/xm32-is-first-inout
32045     0/imm32/no-x32
32046     0x11/imm32/alloc-id:fake
32047     _Primitive-truncate-xreg-to-reg/imm32/next
32048 _Primitive-truncate-xreg-to-reg:  # (payload primitive)
32049     0x11/imm32/alloc-id:fake:payload
32050     # var1/reg <- truncate var2/xreg => f3 0f 2c/truncate-to-int var2/xm32 var1/r32
32051     0x11/imm32/alloc-id:fake
32052     _string-truncate/imm32/name
32053     0x11/imm32/alloc-id:fake
32054     Single-float-var-in-some-register/imm32/inouts
32055     0x11/imm32/alloc-id:fake
32056     Single-int-var-in-some-register/imm32/outputs
32057     0x11/imm32/alloc-id:fake
32058     _string_f3_0f_2c_truncate_to_int/imm32/subx-name
32059     0/imm32/no-rm32
32060     3/imm32/r32-is-first-output
32061     0/imm32/no-imm32
32062     0/imm32/no-imm8
32063     0/imm32/no-disp32
32064     1/imm32/xm32-is-first-inout
32065     0/imm32/no-x32
32066     0x11/imm32/alloc-id:fake
32067     _Primitive-reinterpret-xmem-as-reg/imm32/next
32068 # - reinterpret bytes (just for debugging)
32069 _Primitive-reinterpret-xmem-as-reg:  # (payload primitive)
32070     0x11/imm32/alloc-id:fake:payload
32071     # var1/reg <- reinterpret var2 => 8b/-> var2/xm32 var1/r32
32072     0x11/imm32/alloc-id:fake
32073     _string-reinterpret/imm32/name
32074     0x11/imm32/alloc-id:fake
32075     Single-float-var-in-mem/imm32/inouts
32076     0x11/imm32/alloc-id:fake
32077     Single-int-var-in-some-register/imm32/outputs
32078     0x11/imm32/alloc-id:fake
32079     _string_8b_->/imm32/subx-name
32080     0/imm32/no-rm32
32081     3/imm32/r32-is-first-output
32082     0/imm32/no-imm32
32083     0/imm32/no-imm8
32084     0/imm32/no-disp32
32085     1/imm32/xm32-is-first-inout
32086     0/imm32/no-x32
32087     0x11/imm32/alloc-id:fake
32088     _Primitive-reinterpret-mem-as-xreg/imm32/next
32089 _Primitive-reinterpret-mem-as-xreg:  # (payload primitive)
32090     0x11/imm32/alloc-id:fake:payload
32091     # var1/xreg <- reinterpret var2 => f3 0f 10/-> var2/rm32 var1/x32
32092     0x11/imm32/alloc-id:fake
32093     _string-reinterpret/imm32/name
32094     0x11/imm32/alloc-id:fake
32095     Single-int-var-in-mem/imm32/inouts
32096     0x11/imm32/alloc-id:fake
32097     Single-float-var-in-some-register/imm32/outputs
32098     0x11/imm32/alloc-id:fake
32099     _string_f3_0f_10_copy/imm32/subx-name
32100     1/imm32/rm32-is-first-inout
32101     0/imm32/no-r32
32102     0/imm32/no-imm32
32103     0/imm32/no-imm8
32104     0/imm32/no-disp32
32105     0/imm32/no-xm32
32106     3/imm32/x32-is-first-output
32107     0x11/imm32/alloc-id:fake
32108     _Primitive-copy-xreg-to-xreg/imm32/next
32109 # - floating-point copy
32110 _Primitive-copy-xreg-to-xreg:  # (payload primitive)
32111     0x11/imm32/alloc-id:fake:payload
32112     # var1/xreg <- copy var2/xreg => f3 0f 11/<- var1/xm32 var2/x32
32113     0x11/imm32/alloc-id:fake
32114     _string-copy/imm32/name
32115     0x11/imm32/alloc-id:fake
32116     Single-float-var-in-some-register/imm32/inouts
32117     0x11/imm32/alloc-id:fake
32118     Single-float-var-in-some-register/imm32/outputs
32119     0x11/imm32/alloc-id:fake
32120     _string_f3_0f_11_copy/imm32/subx-name
32121     0/imm32/no-rm32
32122     0/imm32/no-r32
32123     0/imm32/no-imm32
32124     0/imm32/no-imm8
32125     0/imm32/no-disp32
32126     3/imm32/xm32-is-first-output
32127     1/imm32/x32-is-first-inout
32128     0x11/imm32/alloc-id:fake
32129     _Primitive-copy-xreg-to-mem/imm32/next
32130 _Primitive-copy-xreg-to-mem:  # (payload primitive)
32131     0x11/imm32/alloc-id:fake:payload
32132     # copy-to var1 var2/xreg => f3 0f 11/<- var1 var2/x32
32133     0x11/imm32/alloc-id:fake
32134     _string-copy-to/imm32/name
32135     0x11/imm32/alloc-id:fake
32136     Two-args-float-stack-float-reg/imm32/inouts
32137     0/imm32/no-outputs
32138     0/imm32/no-outputs
32139     0x11/imm32/alloc-id:fake
32140     _string_f3_0f_11_copy/imm32/subx-name
32141     0/imm32/no-rm32
32142     0/imm32/no-r32
32143     0/imm32/no-imm32
32144     0/imm32/no-imm8
32145     0/imm32/no-disp32
32146     1/imm32/xm32-is-first-inout
32147     2/imm32/x32-is-second-inout
32148     0x11/imm32/alloc-id:fake
32149     _Primitive-copy-mem-to-xreg/imm32/next
32150 _Primitive-copy-mem-to-xreg:  # (payload primitive)
32151     0x11/imm32/alloc-id:fake:payload
32152     # var1/xreg <- copy var2 => f3 0f 10/-> var2/rm32 var1/x32
32153     0x11/imm32/alloc-id:fake
32154     _string-copy/imm32/name
32155     0x11/imm32/alloc-id:fake
32156     Single-float-var-in-mem/imm32/inouts
32157     0x11/imm32/alloc-id:fake
32158     Single-float-var-in-some-register/imm32/outputs
32159     0x11/imm32/alloc-id:fake
32160     _string_f3_0f_10_copy/imm32/subx-name
32161     0/imm32/no-rm32
32162     0/imm32/no-r32
32163     0/imm32/no-imm32
32164     0/imm32/no-imm8
32165     0/imm32/no-disp32
32166     1/imm32/xm32-is-first-inout
32167     3/imm32/x32-is-first-output
32168     0x11/imm32/alloc-id:fake
32169     _Primitive-address-of-xmem/imm32/next
32170 # - floating-point-address
32171 _Primitive-address-of-xmem:  # (payload primitive)
32172     0x11/imm32/alloc-id:fake:payload
32173     # var1/reg <- address var2 => 8d/copy-address var2/rm32 var1/r32
32174     0x11/imm32/alloc-id:fake
32175     _string-address/imm32/name
32176     0x11/imm32/alloc-id:fake
32177     Single-float-var-in-mem/imm32/inouts
32178     0x11/imm32/alloc-id:fake
32179     Single-addr-var-in-some-register/imm32/outputs
32180     0x11/imm32/alloc-id:fake
32181     _string_8d_copy_address/imm32/subx-name
32182     1/imm32/rm32-is-first-inout
32183     3/imm32/r32-is-first-output
32184     0/imm32/no-imm32
32185     0/imm32/no-imm8
32186     0/imm32/no-disp32
32187     0/imm32/no-xm32
32188     0/imm32/no-x32
32189     0x11/imm32/alloc-id:fake
32190     _Primitive-add-xreg-to-xreg/imm32/next
32191 # - floating-point add
32192 _Primitive-add-xreg-to-xreg:  # (payload primitive)
32193     0x11/imm32/alloc-id:fake:payload
32194     # var1/xreg <- add var2/xreg => f3 0f 58/add var1/xm32 var2/x32
32195     0x11/imm32/alloc-id:fake
32196     _string-add/imm32/name
32197     0x11/imm32/alloc-id:fake
32198     Single-float-var-in-some-register/imm32/inouts
32199     0x11/imm32/alloc-id:fake
32200     Single-float-var-in-some-register/imm32/outputs
32201     0x11/imm32/alloc-id:fake
32202     _string_f3_0f_58_add/imm32/subx-name
32203     0/imm32/no-rm32
32204     0/imm32/no-r32
32205     0/imm32/no-imm32
32206     0/imm32/no-imm8
32207     0/imm32/no-disp32
32208     1/imm32/xm32-is-first-inout
32209     3/imm32/x32-is-first-output
32210     0x11/imm32/alloc-id:fake
32211     _Primitive-add-mem-to-xreg/imm32/next
32212 _Primitive-add-mem-to-xreg:  # (payload primitive)
32213     0x11/imm32/alloc-id:fake:payload
32214     # var1/xreg <- add var2 => f3 0f 58/add var2/xm32 var1/x32
32215     0x11/imm32/alloc-id:fake
32216     _string-add/imm32/name
32217     0x11/imm32/alloc-id:fake
32218     Single-float-var-in-mem/imm32/inouts
32219     0x11/imm32/alloc-id:fake
32220     Single-float-var-in-some-register/imm32/outputs
32221     0x11/imm32/alloc-id:fake
32222     _string_f3_0f_58_add/imm32/subx-name
32223     0/imm32/no-rm32
32224     0/imm32/no-r32
32225     0/imm32/no-imm32
32226     0/imm32/no-imm8
32227     0/imm32/no-disp32
32228     1/imm32/xm32-is-first-inout
32229     3/imm32/x32-is-first-output
32230     0x11/imm32/alloc-id:fake
32231     _Primitive-subtract-xreg-from-xreg/imm32/next
32232 # - floating-point subtract
32233 _Primitive-subtract-xreg-from-xreg:  # (payload primitive)
32234     0x11/imm32/alloc-id:fake:payload
32235     # var1/xreg <- subtract var2/xreg => f3 0f 5c/subtract var1/xm32 var2/x32
32236     0x11/imm32/alloc-id:fake
32237     _string-subtract/imm32/name
32238     0x11/imm32/alloc-id:fake
32239     Single-float-var-in-some-register/imm32/inouts
32240     0x11/imm32/alloc-id:fake
32241     Single-float-var-in-some-register/imm32/outputs
32242     0x11/imm32/alloc-id:fake
32243     _string_f3_0f_5c_subtract/imm32/subx-name
32244     0/imm32/no-rm32
32245     0/imm32/no-r32
32246     0/imm32/no-imm32
32247     0/imm32/no-imm8
32248     0/imm32/no-disp32
32249     1/imm32/xm32-is-first-inout
32250     3/imm32/x32-is-first-output
32251     0x11/imm32/alloc-id:fake
32252     _Primitive-subtract-mem-from-xreg/imm32/next
32253 _Primitive-subtract-mem-from-xreg:  # (payload primitive)
32254     0x11/imm32/alloc-id:fake:payload
32255     # var1/xreg <- subtract var2 => f3 0f 5c/subtract var2/xm32 var1/x32
32256     0x11/imm32/alloc-id:fake
32257     _string-subtract/imm32/name
32258     0x11/imm32/alloc-id:fake
32259     Single-float-var-in-mem/imm32/inouts
32260     0x11/imm32/alloc-id:fake
32261     Single-float-var-in-some-register/imm32/outputs
32262     0x11/imm32/alloc-id:fake
32263     _string_f3_0f_5c_subtract/imm32/subx-name
32264     0/imm32/no-rm32
32265     0/imm32/no-r32
32266     0/imm32/no-imm32
32267     0/imm32/no-imm8
32268     0/imm32/no-disp32
32269     1/imm32/xm32-is-first-inout
32270     3/imm32/x32-is-first-output
32271     0x11/imm32/alloc-id:fake
32272     _Primitive-multiply-xreg-by-xreg/imm32/next
32273 # - floating-point multiply
32274 _Primitive-multiply-xreg-by-xreg:  # (payload primitive)
32275     0x11/imm32/alloc-id:fake:payload
32276     # var1/xreg <- multiply var2 => f3 0f 59/multiply var2/xm32 var1/x32
32277     0x11/imm32/alloc-id:fake
32278     _string-multiply/imm32/name
32279     0x11/imm32/alloc-id:fake
32280     Single-float-var-in-some-register/imm32/inouts
32281     0x11/imm32/alloc-id:fake
32282     Single-float-var-in-some-register/imm32/outputs
32283     0x11/imm32/alloc-id:fake
32284     _string_f3_0f_59_multiply/imm32/subx-name
32285     0/imm32/no-rm32
32286     0/imm32/no-r32
32287     0/imm32/no-imm32
32288     0/imm32/no-imm8
32289     0/imm32/no-disp32
32290     1/imm32/xm32-is-first-inout
32291     3/imm32/x32-is-first-output
32292     0x11/imm32/alloc-id:fake
32293     _Primitive-multiply-xreg-by-mem/imm32/next
32294 _Primitive-multiply-xreg-by-mem:  # (payload primitive)
32295     0x11/imm32/alloc-id:fake:payload
32296     # var1/xreg <- multiply var2 => 53 0f 59/multiply var2/xm32 var1/x32
32297     0x11/imm32/alloc-id:fake
32298     _string-multiply/imm32/name
32299     0x11/imm32/alloc-id:fake
32300     Single-float-var-in-mem/imm32/inouts
32301     0x11/imm32/alloc-id:fake
32302     Single-float-var-in-some-register/imm32/outputs
32303     0x11/imm32/alloc-id:fake
32304     _string_f3_0f_59_multiply/imm32/subx-name
32305     0/imm32/no-rm32
32306     0/imm32/no-r32
32307     0/imm32/no-imm32
32308     0/imm32/no-imm8
32309     0/imm32/no-disp32
32310     1/imm32/xm32-is-first-inout
32311     3/imm32/x32-is-first-output
32312     0x11/imm32/alloc-id:fake
32313     _Primitive-divide-xreg-by-xreg/imm32/next
32314 # - floating-point divide
32315 _Primitive-divide-xreg-by-xreg:  # (payload primitive)
32316     0x11/imm32/alloc-id:fake:payload
32317     # var1/xreg <- divide var2 => f3 0f 5e/divide var2/xm32 var1/x32
32318     0x11/imm32/alloc-id:fake
32319     _string-divide/imm32/name
32320     0x11/imm32/alloc-id:fake
32321     Single-float-var-in-some-register/imm32/inouts
32322     0x11/imm32/alloc-id:fake
32323     Single-float-var-in-some-register/imm32/outputs
32324     0x11/imm32/alloc-id:fake
32325     _string_f3_0f_5e_divide/imm32/subx-name
32326     0/imm32/no-rm32
32327     0/imm32/no-r32
32328     0/imm32/no-imm32
32329     0/imm32/no-imm8
32330     0/imm32/no-disp32
32331     1/imm32/xm32-is-first-inout
32332     3/imm32/x32-is-first-output
32333     0x11/imm32/alloc-id:fake
32334     _Primitive-divide-xreg-by-mem/imm32/next
32335 _Primitive-divide-xreg-by-mem:  # (payload primitive)
32336     0x11/imm32/alloc-id:fake:payload
32337     # var1/xreg <- divide var2 => f3 0f 5e/divide var2/xm32 var1/x32
32338     0x11/imm32/alloc-id:fake
32339     _string-divide/imm32/name
32340     0x11/imm32/alloc-id:fake
32341     Single-float-var-in-mem/imm32/inouts
32342     0x11/imm32/alloc-id:fake
32343     Single-float-var-in-some-register/imm32/outputs
32344     0x11/imm32/alloc-id:fake
32345     _string_f3_0f_5e_divide/imm32/subx-name
32346     0/imm32/no-rm32
32347     0/imm32/no-r32
32348     0/imm32/no-imm32
32349     0/imm32/no-imm8
32350     0/imm32/no-disp32
32351     1/imm32/xm32-is-first-inout
32352     3/imm32/x32-is-first-output
32353     0x11/imm32/alloc-id:fake
32354     _Primitive-max-xreg-with-xreg/imm32/next
32355 # - floating-point maximum
32356 _Primitive-max-xreg-with-xreg:  # (payload primitive)
32357     0x11/imm32/alloc-id:fake:payload
32358     # var1/xreg <- max var2 => f3 0f 5f/max var2/xm32 var1/x32
32359     0x11/imm32/alloc-id:fake
32360     _string-max/imm32/name
32361     0x11/imm32/alloc-id:fake
32362     Single-float-var-in-some-register/imm32/inouts
32363     0x11/imm32/alloc-id:fake
32364     Single-float-var-in-some-register/imm32/outputs
32365     0x11/imm32/alloc-id:fake
32366     _string_f3_0f_5f_max/imm32/subx-name
32367     0/imm32/no-rm32
32368     0/imm32/no-r32
32369     0/imm32/no-imm32
32370     0/imm32/no-imm8
32371     0/imm32/no-disp32
32372     1/imm32/xm32-is-first-inout
32373     3/imm32/x32-is-first-output
32374     0x11/imm32/alloc-id:fake
32375     _Primitive-max-xreg-with-mem/imm32/next
32376 _Primitive-max-xreg-with-mem:  # (payload primitive)
32377     0x11/imm32/alloc-id:fake:payload
32378     # var1/xreg <- divide var2 => f3 0f 5f/max var2/xm32 var1/x32
32379     0x11/imm32/alloc-id:fake
32380     _string-max/imm32/name
32381     0x11/imm32/alloc-id:fake
32382     Single-float-var-in-mem/imm32/inouts
32383     0x11/imm32/alloc-id:fake
32384     Single-float-var-in-some-register/imm32/outputs
32385     0x11/imm32/alloc-id:fake
32386     _string_f3_0f_5f_max/imm32/subx-name
32387     0/imm32/no-rm32
32388     0/imm32/no-r32
32389     0/imm32/no-imm32
32390     0/imm32/no-imm8
32391     0/imm32/no-disp32
32392     1/imm32/xm32-is-first-inout
32393     3/imm32/x32-is-first-output
32394     0x11/imm32/alloc-id:fake
32395     _Primitive-min-xreg-with-xreg/imm32/next
32396 # - floating-point minimum
32397 _Primitive-min-xreg-with-xreg:  # (payload primitive)
32398     0x11/imm32/alloc-id:fake:payload
32399     # var1/xreg <- divide var2 => f3 0f 5d/min var2/xm32 var1/x32
32400     0x11/imm32/alloc-id:fake
32401     _string-min/imm32/name
32402     0x11/imm32/alloc-id:fake
32403     Single-float-var-in-some-register/imm32/inouts
32404     0x11/imm32/alloc-id:fake
32405     Single-float-var-in-some-register/imm32/outputs
32406     0x11/imm32/alloc-id:fake
32407     _string_f3_0f_5d_min/imm32/subx-name
32408     0/imm32/no-rm32
32409     0/imm32/no-r32
32410     0/imm32/no-imm32
32411     0/imm32/no-imm8
32412     0/imm32/no-disp32
32413     1/imm32/xm32-is-first-inout
32414     3/imm32/x32-is-first-output
32415     0x11/imm32/alloc-id:fake
32416     _Primitive-min-xreg-with-mem/imm32/next
32417 _Primitive-min-xreg-with-mem:  # (payload primitive)
32418     0x11/imm32/alloc-id:fake:payload
32419     # var1/xreg <- divide var2 => f3 0f 5d/min var2/xm32 var1/x32
32420     0x11/imm32/alloc-id:fake
32421     _string-min/imm32/name
32422     0x11/imm32/alloc-id:fake
32423     Single-float-var-in-mem/imm32/inouts
32424     0x11/imm32/alloc-id:fake
32425     Single-float-var-in-some-register/imm32/outputs
32426     0x11/imm32/alloc-id:fake
32427     _string_f3_0f_5d_min/imm32/subx-name
32428     0/imm32/no-rm32
32429     0/imm32/no-r32
32430     0/imm32/no-imm32
32431     0/imm32/no-imm8
32432     0/imm32/no-disp32
32433     1/imm32/xm32-is-first-inout
32434     3/imm32/x32-is-first-output
32435     0x11/imm32/alloc-id:fake
32436     _Primitive-reciprocal-xreg-to-xreg/imm32/next
32437 # - floating-point reciprocal
32438 _Primitive-reciprocal-xreg-to-xreg:  # (payload primitive)
32439     0x11/imm32/alloc-id:fake:payload
32440     # var1/xreg <- reciprocal var2 => f3 0f 53/reciprocal var2/xm32 var1/x32
32441     0x11/imm32/alloc-id:fake
32442     _string-reciprocal/imm32/name
32443     0x11/imm32/alloc-id:fake
32444     Single-float-var-in-some-register/imm32/inouts
32445     0x11/imm32/alloc-id:fake
32446     Single-float-var-in-some-register/imm32/outputs
32447     0x11/imm32/alloc-id:fake
32448     _string_f3_0f_53_reciprocal/imm32/subx-name
32449     0/imm32/no-rm32
32450     0/imm32/no-r32
32451     0/imm32/no-imm32
32452     0/imm32/no-imm8
32453     0/imm32/no-disp32
32454     1/imm32/xm32-is-first-inout
32455     3/imm32/x32-is-first-output
32456     0x11/imm32/alloc-id:fake
32457     _Primitive-reciprocal-mem-to-xreg/imm32/next
32458 _Primitive-reciprocal-mem-to-xreg:  # (payload primitive)
32459     0x11/imm32/alloc-id:fake:payload
32460     # var1/xreg <- divide var2 => f3 0f 53/reciprocal var2/xm32 var1/x32
32461     0x11/imm32/alloc-id:fake
32462     _string-reciprocal/imm32/name
32463     0x11/imm32/alloc-id:fake
32464     Single-float-var-in-mem/imm32/inouts
32465     0x11/imm32/alloc-id:fake
32466     Single-float-var-in-some-register/imm32/outputs
32467     0x11/imm32/alloc-id:fake
32468     _string_f3_0f_53_reciprocal/imm32/subx-name
32469     0/imm32/no-rm32
32470     0/imm32/no-r32
32471     0/imm32/no-imm32
32472     0/imm32/no-imm8
32473     0/imm32/no-disp32
32474     1/imm32/xm32-is-first-inout
32475     3/imm32/x32-is-first-output
32476     0x11/imm32/alloc-id:fake
32477     _Primitive-square-root-xreg-to-xreg/imm32/next
32478 # - floating-point square root
32479 _Primitive-square-root-xreg-to-xreg:  # (payload primitive)
32480     0x11/imm32/alloc-id:fake:payload
32481     # var1/xreg <- square-root var2 => f3 0f 51/square-root var2/xm32 var1/x32
32482     0x11/imm32/alloc-id:fake
32483     _string-square-root/imm32/name
32484     0x11/imm32/alloc-id:fake
32485     Single-float-var-in-some-register/imm32/inouts
32486     0x11/imm32/alloc-id:fake
32487     Single-float-var-in-some-register/imm32/outputs
32488     0x11/imm32/alloc-id:fake
32489     _string_f3_0f_51_square_root/imm32/subx-name
32490     0/imm32/no-rm32
32491     0/imm32/no-r32
32492     0/imm32/no-imm32
32493     0/imm32/no-imm8
32494     0/imm32/no-disp32
32495     1/imm32/xm32-is-first-inout
32496     3/imm32/x32-is-first-output
32497     0x11/imm32/alloc-id:fake
32498     _Primitive-square-root-mem-to-xreg/imm32/next
32499 _Primitive-square-root-mem-to-xreg:  # (payload primitive)
32500     0x11/imm32/alloc-id:fake:payload
32501     # var1/xreg <- divide var2 => f3 0f 51/square-root var2/xm32 var1/x32
32502     0x11/imm32/alloc-id:fake
32503     _string-square-root/imm32/name
32504     0x11/imm32/alloc-id:fake
32505     Single-float-var-in-mem/imm32/inouts
32506     0x11/imm32/alloc-id:fake
32507     Single-float-var-in-some-register/imm32/outputs
32508     0x11/imm32/alloc-id:fake
32509     _string_f3_0f_51_square_root/imm32/subx-name
32510     0/imm32/no-rm32
32511     0/imm32/no-r32
32512     0/imm32/no-imm32
32513     0/imm32/no-imm8
32514     0/imm32/no-disp32
32515     1/imm32/xm32-is-first-inout
32516     3/imm32/x32-is-first-output
32517     0x11/imm32/alloc-id:fake
32518     _Primitive-inverse-square-root-xreg-to-xreg/imm32/next
32519 # - floating-point inverse square root 1/sqrt(x)
32520 _Primitive-inverse-square-root-xreg-to-xreg:  # (payload primitive)
32521     0x11/imm32/alloc-id:fake:payload
32522     # var1/xreg <- reciprocal var2 => f3 0f 52/inverse-square-root var2/xm32 var1/x32
32523     0x11/imm32/alloc-id:fake
32524     _string-inverse-square-root/imm32/name
32525     0x11/imm32/alloc-id:fake
32526     Single-float-var-in-some-register/imm32/inouts
32527     0x11/imm32/alloc-id:fake
32528     Single-float-var-in-some-register/imm32/outputs
32529     0x11/imm32/alloc-id:fake
32530     _string_f3_0f_52_inverse_square_root/imm32/subx-name
32531     0/imm32/no-rm32
32532     0/imm32/no-r32
32533     0/imm32/no-imm32
32534     0/imm32/no-imm8
32535     0/imm32/no-disp32
32536     1/imm32/xm32-is-first-inout
32537     3/imm32/x32-is-first-output
32538     0x11/imm32/alloc-id:fake
32539     _Primitive-inverse-square-root-mem-to-xreg/imm32/next
32540 _Primitive-inverse-square-root-mem-to-xreg:  # (payload primitive)
32541     0x11/imm32/alloc-id:fake:payload
32542     # var1/xreg <- divide var2 => f3 0f 52/inverse-square-root var2/xm32 var1/x32
32543     0x11/imm32/alloc-id:fake
32544     _string-inverse-square-root/imm32/name
32545     0x11/imm32/alloc-id:fake
32546     Single-float-var-in-mem/imm32/inouts
32547     0x11/imm32/alloc-id:fake
32548     Single-float-var-in-some-register/imm32/outputs
32549     0x11/imm32/alloc-id:fake
32550     _string_f3_0f_52_inverse_square_root/imm32/subx-name
32551     0/imm32/no-rm32
32552     0/imm32/no-r32
32553     0/imm32/no-imm32
32554     0/imm32/no-imm8
32555     0/imm32/no-disp32
32556     1/imm32/xm32-is-first-inout
32557     3/imm32/x32-is-first-output
32558     0x11/imm32/alloc-id:fake
32559     _Primitive-compare-xreg-with-xreg/imm32/next
32560 # - floating-point compare
32561 _Primitive-compare-xreg-with-xreg:  # (payload primitive)
32562     0x11/imm32/alloc-id:fake:payload
32563     # compare var1/reg1 var2/reg2 => 0f 2f/compare var2/x32 var1/xm32
32564     0x11/imm32/alloc-id:fake
32565     _string-compare/imm32/name
32566     0x11/imm32/alloc-id:fake
32567     Two-float-args-in-regs/imm32/inouts
32568     0/imm32/no-outputs
32569     0/imm32/no-outputs
32570     0x11/imm32/alloc-id:fake
32571     _string_0f_2f_compare/imm32/subx-name
32572     0/imm32/no-rm32
32573     0/imm32/no-r32
32574     0/imm32/no-imm32
32575     0/imm32/no-imm8
32576     0/imm32/no-disp32
32577     2/imm32/xm32-is-second-inout
32578     1/imm32/x32-is-first-inout
32579     0x11/imm32/alloc-id:fake
32580     _Primitive-compare-xreg-with-mem/imm32/next
32581 _Primitive-compare-xreg-with-mem:  # (payload primitive)
32582     0x11/imm32/alloc-id:fake:payload
32583     # compare var1/xreg var2 => 0f 2f/compare var1/x32 var2/xm32
32584     0x11/imm32/alloc-id:fake
32585     _string-compare/imm32/name
32586     0x11/imm32/alloc-id:fake
32587     Two-args-float-reg-float-stack/imm32/inouts
32588     0/imm32/no-outputs
32589     0/imm32/no-outputs
32590     0x11/imm32/alloc-id:fake
32591     _string_0f_2f_compare/imm32/subx-name
32592     0/imm32/no-rm32
32593     0/imm32/no-r32
32594     0/imm32/no-imm32
32595     0/imm32/no-imm8
32596     0/imm32/no-disp32
32597     2/imm32/xm32-is-second-inout
32598     1/imm32/x32-is-first-inout
32599     0x11/imm32/alloc-id:fake
32600     _Primitive-break-if-addr</imm32/next
32601 # - branches
32602 _Primitive-break-if-addr<:  # (payload primitive)
32603     0x11/imm32/alloc-id:fake:payload
32604     0x11/imm32/alloc-id:fake
32605     _string-break-if-addr</imm32/name
32606     0/imm32/no-inouts
32607     0/imm32/no-inouts
32608     0/imm32/no-outputs
32609     0/imm32/no-outputs
32610     0x11/imm32/alloc-id:fake
32611     _string_0f_82_jump_break/imm32/subx-name
32612     0/imm32/no-rm32
32613     0/imm32/no-r32
32614     0/imm32/no-imm32
32615     0/imm32/no-imm8
32616     0/imm32/no-disp32
32617     0/imm32/no-xm32
32618     0/imm32/no-x32
32619     0x11/imm32/alloc-id:fake
32620     _Primitive-break-if-addr>=/imm32/next
32621 _Primitive-break-if-addr>=:  # (payload primitive)
32622     0x11/imm32/alloc-id:fake:payload
32623     0x11/imm32/alloc-id:fake
32624     _string-break-if-addr>=/imm32/name
32625     0/imm32/no-inouts
32626     0/imm32/no-inouts
32627     0/imm32/no-outputs
32628     0/imm32/no-outputs
32629     0x11/imm32/alloc-id:fake
32630     _string_0f_83_jump_break/imm32/subx-name
32631     0/imm32/no-rm32
32632     0/imm32/no-r32
32633     0/imm32/no-imm32
32634     0/imm32/no-imm8
32635     0/imm32/no-disp32
32636     0/imm32/no-xm32
32637     0/imm32/no-x32
32638     0x11/imm32/alloc-id:fake
32639     _Primitive-break-if-=/imm32/next
32640 _Primitive-break-if-=:  # (payload primitive)
32641     0x11/imm32/alloc-id:fake:payload
32642     0x11/imm32/alloc-id:fake
32643     _string-break-if-=/imm32/name
32644     0/imm32/no-inouts
32645     0/imm32/no-inouts
32646     0/imm32/no-outputs
32647     0/imm32/no-outputs
32648     0x11/imm32/alloc-id:fake
32649     _string_0f_84_jump_break/imm32/subx-name
32650     0/imm32/no-rm32
32651     0/imm32/no-r32
32652     0/imm32/no-imm32
32653     0/imm32/no-imm8
32654     0/imm32/no-disp32
32655     0/imm32/no-xm32
32656     0/imm32/no-x32
32657     0x11/imm32/alloc-id:fake
32658     _Primitive-break-if-!=/imm32/next
32659 _Primitive-break-if-!=:  # (payload primitive)
32660     0x11/imm32/alloc-id:fake:payload
32661     0x11/imm32/alloc-id:fake
32662     _string-break-if-!=/imm32/name
32663     0/imm32/no-inouts
32664     0/imm32/no-inouts
32665     0/imm32/no-outputs
32666     0/imm32/no-outputs
32667     0x11/imm32/alloc-id:fake
32668     _string_0f_85_jump_break/imm32/subx-name
32669     0/imm32/no-rm32
32670     0/imm32/no-r32
32671     0/imm32/no-imm32
32672     0/imm32/no-imm8
32673     0/imm32/no-disp32
32674     0/imm32/no-xm32
32675     0/imm32/no-x32
32676     0x11/imm32/alloc-id:fake
32677     _Primitive-break-if-addr<=/imm32/next
32678 _Primitive-break-if-addr<=:  # (payload primitive)
32679     0x11/imm32/alloc-id:fake:payload
32680     0x11/imm32/alloc-id:fake
32681     _string-break-if-addr<=/imm32/name
32682     0/imm32/no-inouts
32683     0/imm32/no-inouts
32684     0/imm32/no-outputs
32685     0/imm32/no-outputs
32686     0x11/imm32/alloc-id:fake
32687     _string_0f_86_jump_break/imm32/subx-name
32688     0/imm32/no-rm32
32689     0/imm32/no-r32
32690     0/imm32/no-imm32
32691     0/imm32/no-imm8
32692     0/imm32/no-disp32
32693     0/imm32/no-xm32
32694     0/imm32/no-x32
32695     0x11/imm32/alloc-id:fake
32696     _Primitive-break-if-addr>/imm32/next
32697 _Primitive-break-if-addr>:  # (payload primitive)
32698     0x11/imm32/alloc-id:fake:payload
32699     0x11/imm32/alloc-id:fake
32700     _string-break-if-addr>/imm32/name
32701     0/imm32/no-inouts
32702     0/imm32/no-inouts
32703     0/imm32/no-outputs
32704     0/imm32/no-outputs
32705     0x11/imm32/alloc-id:fake
32706     _string_0f_87_jump_break/imm32/subx-name
32707     0/imm32/no-rm32
32708     0/imm32/no-r32
32709     0/imm32/no-imm32
32710     0/imm32/no-imm8
32711     0/imm32/no-disp32
32712     0/imm32/no-xm32
32713     0/imm32/no-x32
32714     0x11/imm32/alloc-id:fake
32715     _Primitive-break-if-</imm32/next
32716 _Primitive-break-if-<:  # (payload primitive)
32717     0x11/imm32/alloc-id:fake:payload
32718     0x11/imm32/alloc-id:fake
32719     _string-break-if-</imm32/name
32720     0/imm32/no-inouts
32721     0/imm32/no-inouts
32722     0/imm32/no-outputs
32723     0/imm32/no-outputs
32724     0x11/imm32/alloc-id:fake
32725     _string_0f_8c_jump_break/imm32/subx-name
32726     0/imm32/no-rm32
32727     0/imm32/no-r32
32728     0/imm32/no-imm32
32729     0/imm32/no-imm8
32730     0/imm32/no-disp32
32731     0/imm32/no-xm32
32732     0/imm32/no-x32
32733     0x11/imm32/alloc-id:fake
32734     _Primitive-break-if->=/imm32/next
32735 _Primitive-break-if->=:  # (payload primitive)
32736     0x11/imm32/alloc-id:fake:payload
32737     0x11/imm32/alloc-id:fake
32738     _string-break-if->=/imm32/name
32739     0/imm32/no-inouts
32740     0/imm32/no-inouts
32741     0/imm32/no-outputs
32742     0/imm32/no-outputs
32743     0x11/imm32/alloc-id:fake
32744     _string_0f_8d_jump_break/imm32/subx-name
32745     0/imm32/no-rm32
32746     0/imm32/no-r32
32747     0/imm32/no-imm32
32748     0/imm32/no-imm8
32749     0/imm32/no-disp32
32750     0/imm32/no-xm32
32751     0/imm32/no-x32
32752     0x11/imm32/alloc-id:fake
32753     _Primitive-break-if-<=/imm32/next
32754 _Primitive-break-if-<=:  # (payload primitive)
32755     0x11/imm32/alloc-id:fake:payload
32756     0x11/imm32/alloc-id:fake
32757     _string-break-if-<=/imm32/name
32758     0/imm32/no-inouts
32759     0/imm32/no-inouts
32760     0/imm32/no-outputs
32761     0/imm32/no-outputs
32762     0x11/imm32/alloc-id:fake
32763     _string_0f_8e_jump_break/imm32/subx-name
32764     0/imm32/no-rm32
32765     0/imm32/no-r32
32766     0/imm32/no-imm32
32767     0/imm32/no-imm8
32768     0/imm32/no-disp32
32769     0/imm32/no-xm32
32770     0/imm32/no-x32
32771     0x11/imm32/alloc-id:fake
32772     _Primitive-break-if->/imm32/next
32773 _Primitive-break-if->:  # (payload primitive)
32774     0x11/imm32/alloc-id:fake:payload
32775     0x11/imm32/alloc-id:fake
32776     _string-break-if->/imm32/name
32777     0/imm32/no-inouts
32778     0/imm32/no-inouts
32779     0/imm32/no-outputs
32780     0/imm32/no-outputs
32781     0x11/imm32/alloc-id:fake
32782     _string_0f_8f_jump_break/imm32/subx-name
32783     0/imm32/no-rm32
32784     0/imm32/no-r32
32785     0/imm32/no-imm32
32786     0/imm32/no-imm8
32787     0/imm32/no-disp32
32788     0/imm32/no-xm32
32789     0/imm32/no-x32
32790     0x11/imm32/alloc-id:fake
32791     _Primitive-break/imm32/next
32792 _Primitive-break:  # (payload primitive)
32793     0x11/imm32/alloc-id:fake:payload
32794     0x11/imm32/alloc-id:fake
32795     _string-break/imm32/name
32796     0/imm32/no-inouts
32797     0/imm32/no-inouts
32798     0/imm32/no-outputs
32799     0/imm32/no-outputs
32800     0x11/imm32/alloc-id:fake
32801     _string_e9_jump_break/imm32/subx-name
32802     0/imm32/no-rm32
32803     0/imm32/no-r32
32804     0/imm32/no-imm32
32805     0/imm32/no-imm8
32806     0/imm32/no-disp32
32807     0/imm32/no-xm32
32808     0/imm32/no-x32
32809     0x11/imm32/alloc-id:fake
32810     _Primitive-loop-if-addr</imm32/next
32811 _Primitive-loop-if-addr<:  # (payload primitive)
32812     0x11/imm32/alloc-id:fake:payload
32813     0x11/imm32/alloc-id:fake
32814     _string-loop-if-addr</imm32/name
32815     0/imm32/no-inouts
32816     0/imm32/no-inouts
32817     0/imm32/no-outputs
32818     0/imm32/no-outputs
32819     0x11/imm32/alloc-id:fake
32820     _string_0f_82_jump_loop/imm32/subx-name
32821     0/imm32/no-rm32
32822     0/imm32/no-r32
32823     0/imm32/no-imm32
32824     0/imm32/no-imm8
32825     0/imm32/no-disp32
32826     0/imm32/no-xm32
32827     0/imm32/no-x32
32828     0x11/imm32/alloc-id:fake
32829     _Primitive-loop-if-addr>=/imm32/next
32830 _Primitive-loop-if-addr>=:  # (payload primitive)
32831     0x11/imm32/alloc-id:fake:payload
32832     0x11/imm32/alloc-id:fake
32833     _string-loop-if-addr>=/imm32/name
32834     0/imm32/no-inouts
32835     0/imm32/no-inouts
32836     0/imm32/no-outputs
32837     0/imm32/no-outputs
32838     0x11/imm32/alloc-id:fake
32839     _string_0f_83_jump_loop/imm32/subx-name
32840     0/imm32/no-rm32
32841     0/imm32/no-r32
32842     0/imm32/no-imm32
32843     0/imm32/no-imm8
32844     0/imm32/no-disp32
32845     0/imm32/no-xm32
32846     0/imm32/no-x32
32847     0x11/imm32/alloc-id:fake
32848     _Primitive-loop-if-=/imm32/next
32849 _Primitive-loop-if-=:  # (payload primitive)
32850     0x11/imm32/alloc-id:fake:payload
32851     0x11/imm32/alloc-id:fake
32852     _string-loop-if-=/imm32/name
32853     0/imm32/no-inouts
32854     0/imm32/no-inouts
32855     0/imm32/no-outputs
32856     0/imm32/no-outputs
32857     0x11/imm32/alloc-id:fake
32858     _string_0f_84_jump_loop/imm32/subx-name
32859     0/imm32/no-rm32
32860     0/imm32/no-r32
32861     0/imm32/no-imm32
32862     0/imm32/no-imm8
32863     0/imm32/no-disp32
32864     0/imm32/no-xm32
32865     0/imm32/no-x32
32866     0x11/imm32/alloc-id:fake
32867     _Primitive-loop-if-!=/imm32/next
32868 _Primitive-loop-if-!=:  # (payload primitive)
32869     0x11/imm32/alloc-id:fake:payload
32870     0x11/imm32/alloc-id:fake
32871     _string-loop-if-!=/imm32/name
32872     0/imm32/no-inouts
32873     0/imm32/no-inouts
32874     0/imm32/no-outputs
32875     0/imm32/no-outputs
32876     0x11/imm32/alloc-id:fake
32877     _string_0f_85_jump_loop/imm32/subx-name
32878     0/imm32/no-rm32
32879     0/imm32/no-r32
32880     0/imm32/no-imm32
32881     0/imm32/no-imm8
32882     0/imm32/no-disp32
32883     0/imm32/no-xm32
32884     0/imm32/no-x32
32885     0x11/imm32/alloc-id:fake
32886     _Primitive-loop-if-addr<=/imm32/next
32887 _Primitive-loop-if-addr<=:  # (payload primitive)
32888     0x11/imm32/alloc-id:fake:payload
32889     0x11/imm32/alloc-id:fake
32890     _string-loop-if-addr<=/imm32/name
32891     0/imm32/no-inouts
32892     0/imm32/no-inouts
32893     0/imm32/no-outputs
32894     0/imm32/no-outputs
32895     0x11/imm32/alloc-id:fake
32896     _string_0f_86_jump_loop/imm32/subx-name
32897     0/imm32/no-rm32
32898     0/imm32/no-r32
32899     0/imm32/no-imm32
32900     0/imm32/no-imm8
32901     0/imm32/no-disp32
32902     0/imm32/no-xm32
32903     0/imm32/no-x32
32904     0x11/imm32/alloc-id:fake
32905     _Primitive-loop-if-addr>/imm32/next
32906 _Primitive-loop-if-addr>:  # (payload primitive)
32907     0x11/imm32/alloc-id:fake:payload
32908     0x11/imm32/alloc-id:fake
32909     _string-loop-if-addr>/imm32/name
32910     0/imm32/no-inouts
32911     0/imm32/no-inouts
32912     0/imm32/no-outputs
32913     0/imm32/no-outputs
32914     0x11/imm32/alloc-id:fake
32915     _string_0f_87_jump_loop/imm32/subx-name
32916     0/imm32/no-rm32
32917     0/imm32/no-r32
32918     0/imm32/no-imm32
32919     0/imm32/no-imm8
32920     0/imm32/no-disp32
32921     0/imm32/no-xm32
32922     0/imm32/no-x32
32923     0x11/imm32/alloc-id:fake
32924     _Primitive-loop-if-</imm32/next
32925 _Primitive-loop-if-<:  # (payload primitive)
32926     0x11/imm32/alloc-id:fake:payload
32927     0x11/imm32/alloc-id:fake
32928     _string-loop-if-</imm32/name
32929     0/imm32/no-inouts
32930     0/imm32/no-inouts
32931     0/imm32/no-outputs
32932     0/imm32/no-outputs
32933     0x11/imm32/alloc-id:fake
32934     _string_0f_8c_jump_loop/imm32/subx-name
32935     0/imm32/no-rm32
32936     0/imm32/no-r32
32937     0/imm32/no-imm32
32938     0/imm32/no-imm8
32939     0/imm32/no-disp32
32940     0/imm32/no-xm32
32941     0/imm32/no-x32
32942     0x11/imm32/alloc-id:fake
32943     _Primitive-loop-if->=/imm32/next
32944 _Primitive-loop-if->=:  # (payload primitive)
32945     0x11/imm32/alloc-id:fake:payload
32946     0x11/imm32/alloc-id:fake
32947     _string-loop-if->=/imm32/name
32948     0/imm32/no-inouts
32949     0/imm32/no-inouts
32950     0/imm32/no-outputs
32951     0/imm32/no-outputs
32952     0x11/imm32/alloc-id:fake
32953     _string_0f_8d_jump_loop/imm32/subx-name
32954     0/imm32/no-rm32
32955     0/imm32/no-r32
32956     0/imm32/no-imm32
32957     0/imm32/no-imm8
32958     0/imm32/no-disp32
32959     0/imm32/no-xm32
32960     0/imm32/no-x32
32961     0x11/imm32/alloc-id:fake
32962     _Primitive-loop-if-<=/imm32/next
32963 _Primitive-loop-if-<=:  # (payload primitive)
32964     0x11/imm32/alloc-id:fake:payload
32965     0x11/imm32/alloc-id:fake
32966     _string-loop-if-<=/imm32/name
32967     0/imm32/no-inouts
32968     0/imm32/no-inouts
32969     0/imm32/no-outputs
32970     0/imm32/no-outputs
32971     0x11/imm32/alloc-id:fake
32972     _string_0f_8e_jump_loop/imm32/subx-name
32973     0/imm32/no-rm32
32974     0/imm32/no-r32
32975     0/imm32/no-imm32
32976     0/imm32/no-imm8
32977     0/imm32/no-disp32
32978     0/imm32/no-xm32
32979     0/imm32/no-x32
32980     0x11/imm32/alloc-id:fake
32981     _Primitive-loop-if->/imm32/next
32982 _Primitive-loop-if->:  # (payload primitive)
32983     0x11/imm32/alloc-id:fake:payload
32984     0x11/imm32/alloc-id:fake
32985     _string-loop-if->/imm32/name
32986     0/imm32/no-inouts
32987     0/imm32/no-inouts
32988     0/imm32/no-outputs
32989     0/imm32/no-outputs
32990     0x11/imm32/alloc-id:fake
32991     _string_0f_8f_jump_loop/imm32/subx-name
32992     0/imm32/no-rm32
32993     0/imm32/no-r32
32994     0/imm32/no-imm32
32995     0/imm32/no-imm8
32996     0/imm32/no-disp32
32997     0/imm32/no-xm32
32998     0/imm32/no-x32
32999     0x11/imm32/alloc-id:fake
33000     _Primitive-loop/imm32/next  # we probably don't need an unconditional break
33001 _Primitive-loop:  # (payload primitive)
33002     0x11/imm32/alloc-id:fake:payload
33003     0x11/imm32/alloc-id:fake
33004     _string-loop/imm32/name
33005     0/imm32/no-inouts
33006     0/imm32/no-inouts
33007     0/imm32/no-outputs
33008     0/imm32/no-outputs
33009     0x11/imm32/alloc-id:fake
33010     _string_e9_jump_loop/imm32/subx-name
33011     0/imm32/no-rm32
33012     0/imm32/no-r32
33013     0/imm32/no-imm32
33014     0/imm32/no-imm8
33015     0/imm32/no-disp32
33016     0/imm32/no-xm32
33017     0/imm32/no-x32
33018     0x11/imm32/alloc-id:fake
33019     _Primitive-break-if-addr<-named/imm32/next
33020 # - branches to named blocks
33021 _Primitive-break-if-addr<-named:  # (payload primitive)
33022     0x11/imm32/alloc-id:fake:payload
33023     0x11/imm32/alloc-id:fake
33024     _string-break-if-addr</imm32/name
33025     0x11/imm32/alloc-id:fake
33026     Single-lit-var/imm32/inouts
33027     0/imm32/no-outputs
33028     0/imm32/no-outputs
33029     0x11/imm32/alloc-id:fake
33030     _string_0f_82_jump_label/imm32/subx-name
33031     0/imm32/no-rm32
33032     0/imm32/no-r32
33033     0/imm32/no-imm32
33034     0/imm32/no-imm8
33035     1/imm32/disp32-is-first-inout
33036     0/imm32/no-xm32
33037     0/imm32/no-x32
33038     0x11/imm32/alloc-id:fake
33039     _Primitive-break-if-addr>=-named/imm32/next
33040 _Primitive-break-if-addr>=-named:  # (payload primitive)
33041     0x11/imm32/alloc-id:fake:payload
33042     0x11/imm32/alloc-id:fake
33043     _string-break-if-addr>=/imm32/name
33044     0x11/imm32/alloc-id:fake
33045     Single-lit-var/imm32/inouts
33046     0/imm32/no-outputs
33047     0/imm32/no-outputs
33048     0x11/imm32/alloc-id:fake
33049     _string_0f_83_jump_label/imm32/subx-name
33050     0/imm32/no-rm32
33051     0/imm32/no-r32
33052     0/imm32/no-imm32
33053     0/imm32/no-imm8
33054     1/imm32/disp32-is-first-inout
33055     0/imm32/no-xm32
33056     0/imm32/no-x32
33057     0x11/imm32/alloc-id:fake
33058     _Primitive-break-if-=-named/imm32/next
33059 _Primitive-break-if-=-named:  # (payload primitive)
33060     0x11/imm32/alloc-id:fake:payload
33061     0x11/imm32/alloc-id:fake
33062     _string-break-if-=/imm32/name
33063     0x11/imm32/alloc-id:fake
33064     Single-lit-var/imm32/inouts
33065     0/imm32/no-outputs
33066     0/imm32/no-outputs
33067     0x11/imm32/alloc-id:fake
33068     _string_0f_84_jump_label/imm32/subx-name
33069     0/imm32/no-rm32
33070     0/imm32/no-r32
33071     0/imm32/no-imm32
33072     0/imm32/no-imm8
33073     1/imm32/disp32-is-first-inout
33074     0/imm32/no-xm32
33075     0/imm32/no-x32
33076     0x11/imm32/alloc-id:fake
33077     _Primitive-break-if-!=-named/imm32/next
33078 _Primitive-break-if-!=-named:  # (payload primitive)
33079     0x11/imm32/alloc-id:fake:payload
33080     0x11/imm32/alloc-id:fake
33081     _string-break-if-!=/imm32/name
33082     0x11/imm32/alloc-id:fake
33083     Single-lit-var/imm32/inouts
33084     0/imm32/no-outputs
33085     0/imm32/no-outputs
33086     0x11/imm32/alloc-id:fake
33087     _string_0f_85_jump_label/imm32/subx-name
33088     0/imm32/no-rm32
33089     0/imm32/no-r32
33090     0/imm32/no-imm32
33091     0/imm32/no-imm8
33092     1/imm32/disp32-is-first-inout
33093     0/imm32/no-xm32
33094     0/imm32/no-x32
33095     0x11/imm32/alloc-id:fake
33096     _Primitive-break-if-addr<=-named/imm32/next
33097 _Primitive-break-if-addr<=-named:  # (payload primitive)
33098     0x11/imm32/alloc-id:fake:payload
33099     0x11/imm32/alloc-id:fake
33100     _string-break-if-addr<=/imm32/name
33101     0x11/imm32/alloc-id:fake
33102     Single-lit-var/imm32/inouts
33103     0/imm32/no-outputs
33104     0/imm32/no-outputs
33105     0x11/imm32/alloc-id:fake
33106     _string_0f_86_jump_label/imm32/subx-name
33107     0/imm32/no-rm32
33108     0/imm32/no-r32
33109     0/imm32/no-imm32
33110     0/imm32/no-imm8
33111     1/imm32/disp32-is-first-inout
33112     0/imm32/no-xm32
33113     0/imm32/no-x32
33114     0x11/imm32/alloc-id:fake
33115     _Primitive-break-if-addr>-named/imm32/next
33116 _Primitive-break-if-addr>-named:  # (payload primitive)
33117     0x11/imm32/alloc-id:fake:payload
33118     0x11/imm32/alloc-id:fake
33119     _string-break-if-addr>/imm32/name
33120     0x11/imm32/alloc-id:fake
33121     Single-lit-var/imm32/inouts
33122     0/imm32/no-outputs
33123     0/imm32/no-outputs
33124     0x11/imm32/alloc-id:fake
33125     _string_0f_87_jump_label/imm32/subx-name
33126     0/imm32/no-rm32
33127     0/imm32/no-r32
33128     0/imm32/no-imm32
33129     0/imm32/no-imm8
33130     1/imm32/disp32-is-first-inout
33131     0/imm32/no-xm32
33132     0/imm32/no-x32
33133     0x11/imm32/alloc-id:fake
33134     _Primitive-break-if-<-named/imm32/next
33135 _Primitive-break-if-<-named:  # (payload primitive)
33136     0x11/imm32/alloc-id:fake:payload
33137     0x11/imm32/alloc-id:fake
33138     _string-break-if-</imm32/name
33139     0x11/imm32/alloc-id:fake
33140     Single-lit-var/imm32/inouts
33141     0/imm32/no-outputs
33142     0/imm32/no-outputs
33143     0x11/imm32/alloc-id:fake
33144     _string_0f_8c_jump_label/imm32/subx-name
33145     0/imm32/no-rm32
33146     0/imm32/no-r32
33147     0/imm32/no-imm32
33148     0/imm32/no-imm8
33149     1/imm32/disp32-is-first-inout
33150     0/imm32/no-xm32
33151     0/imm32/no-x32
33152     0x11/imm32/alloc-id:fake
33153     _Primitive-break-if->=-named/imm32/next
33154 _Primitive-break-if->=-named:  # (payload primitive)
33155     0x11/imm32/alloc-id:fake:payload
33156     0x11/imm32/alloc-id:fake
33157     _string-break-if->=/imm32/name
33158     0x11/imm32/alloc-id:fake
33159     Single-lit-var/imm32/inouts
33160     0/imm32/no-outputs
33161     0/imm32/no-outputs
33162     0x11/imm32/alloc-id:fake
33163     _string_0f_8d_jump_label/imm32/subx-name
33164     0/imm32/no-rm32
33165     0/imm32/no-r32
33166     0/imm32/no-imm32
33167     0/imm32/no-imm8
33168     1/imm32/disp32-is-first-inout
33169     0/imm32/no-xm32
33170     0/imm32/no-x32
33171     0x11/imm32/alloc-id:fake
33172     _Primitive-break-if-<=-named/imm32/next
33173 _Primitive-break-if-<=-named:  # (payload primitive)
33174     0x11/imm32/alloc-id:fake:payload
33175     0x11/imm32/alloc-id:fake
33176     _string-break-if-<=/imm32/name
33177     0x11/imm32/alloc-id:fake
33178     Single-lit-var/imm32/inouts
33179     0/imm32/no-outputs
33180     0/imm32/no-outputs
33181     0x11/imm32/alloc-id:fake
33182     _string_0f_8e_jump_label/imm32/subx-name
33183     0/imm32/no-rm32
33184     0/imm32/no-r32
33185     0/imm32/no-imm32
33186     0/imm32/no-imm8
33187     1/imm32/disp32-is-first-inout
33188     0/imm32/no-xm32
33189     0/imm32/no-x32
33190     0x11/imm32/alloc-id:fake
33191     _Primitive-break-if->-named/imm32/next
33192 _Primitive-break-if->-named:  # (payload primitive)
33193     0x11/imm32/alloc-id:fake:payload
33194     0x11/imm32/alloc-id:fake
33195     _string-break-if->/imm32/name
33196     0x11/imm32/alloc-id:fake
33197     Single-lit-var/imm32/inouts
33198     0/imm32/no-outputs
33199     0/imm32/no-outputs
33200     0x11/imm32/alloc-id:fake
33201     _string_0f_8f_jump_label/imm32/subx-name
33202     0/imm32/no-rm32
33203     0/imm32/no-r32
33204     0/imm32/no-imm32
33205     0/imm32/no-imm8
33206     1/imm32/disp32-is-first-inout
33207     0/imm32/no-xm32
33208     0/imm32/no-x32
33209     0x11/imm32/alloc-id:fake
33210     _Primitive-break-named/imm32/next
33211 _Primitive-break-named:  # (payload primitive)
33212     0x11/imm32/alloc-id:fake:payload
33213     0x11/imm32/alloc-id:fake
33214     _string-break/imm32/name
33215     0x11/imm32/alloc-id:fake
33216     Single-lit-var/imm32/inouts
33217     0/imm32/no-outputs
33218     0/imm32/no-outputs
33219     0x11/imm32/alloc-id:fake
33220     _string_e9_jump_label/imm32/subx-name
33221     0/imm32/no-rm32
33222     0/imm32/no-r32
33223     0/imm32/no-imm32
33224     0/imm32/no-imm8
33225     1/imm32/disp32-is-first-inout
33226     0/imm32/no-xm32
33227     0/imm32/no-x32
33228     0x11/imm32/alloc-id:fake
33229     _Primitive-loop-if-addr<-named/imm32/next
33230 _Primitive-loop-if-addr<-named:  # (payload primitive)
33231     0x11/imm32/alloc-id:fake:payload
33232     0x11/imm32/alloc-id:fake
33233     _string-loop-if-addr</imm32/name
33234     0x11/imm32/alloc-id:fake
33235     Single-lit-var/imm32/inouts
33236     0/imm32/no-outputs
33237     0/imm32/no-outputs
33238     0x11/imm32/alloc-id:fake
33239     _string_0f_82_jump_label/imm32/subx-name
33240     0/imm32/no-rm32
33241     0/imm32/no-r32
33242     0/imm32/no-imm32
33243     0/imm32/no-imm8
33244     1/imm32/disp32-is-first-inout
33245     0/imm32/no-xm32
33246     0/imm32/no-x32
33247     0x11/imm32/alloc-id:fake
33248     _Primitive-loop-if-addr>=-named/imm32/next
33249 _Primitive-loop-if-addr>=-named:  # (payload primitive)
33250     0x11/imm32/alloc-id:fake:payload
33251     0x11/imm32/alloc-id:fake
33252     _string-loop-if-addr>=/imm32/name
33253     0x11/imm32/alloc-id:fake
33254     Single-lit-var/imm32/inouts
33255     0/imm32/no-outputs
33256     0/imm32/no-outputs
33257     0x11/imm32/alloc-id:fake
33258     _string_0f_83_jump_label/imm32/subx-name
33259     0/imm32/no-rm32
33260     0/imm32/no-r32
33261     0/imm32/no-imm32
33262     0/imm32/no-imm8
33263     1/imm32/disp32-is-first-inout
33264     0/imm32/no-xm32
33265     0/imm32/no-x32
33266     0x11/imm32/alloc-id:fake
33267     _Primitive-loop-if-=-named/imm32/next
33268 _Primitive-loop-if-=-named:  # (payload primitive)
33269     0x11/imm32/alloc-id:fake:payload
33270     0x11/imm32/alloc-id:fake
33271     _string-loop-if-=/imm32/name
33272     0x11/imm32/alloc-id:fake
33273     Single-lit-var/imm32/inouts
33274     0/imm32/no-outputs
33275     0/imm32/no-outputs
33276     0x11/imm32/alloc-id:fake
33277     _string_0f_84_jump_label/imm32/subx-name
33278     0/imm32/no-rm32
33279     0/imm32/no-r32
33280     0/imm32/no-imm32
33281     0/imm32/no-imm8
33282     1/imm32/disp32-is-first-inout
33283     0/imm32/no-xm32
33284     0/imm32/no-x32
33285     0x11/imm32/alloc-id:fake
33286     _Primitive-loop-if-!=-named/imm32/next
33287 _Primitive-loop-if-!=-named:  # (payload primitive)
33288     0x11/imm32/alloc-id:fake:payload
33289     0x11/imm32/alloc-id:fake
33290     _string-loop-if-!=/imm32/name
33291     0x11/imm32/alloc-id:fake
33292     Single-lit-var/imm32/inouts
33293     0/imm32/no-outputs
33294     0/imm32/no-outputs
33295     0x11/imm32/alloc-id:fake
33296     _string_0f_85_jump_label/imm32/subx-name
33297     0/imm32/no-rm32
33298     0/imm32/no-r32
33299     0/imm32/no-imm32
33300     0/imm32/no-imm8
33301     1/imm32/disp32-is-first-inout
33302     0/imm32/no-xm32
33303     0/imm32/no-x32
33304     0x11/imm32/alloc-id:fake
33305     _Primitive-loop-if-addr<=-named/imm32/next
33306 _Primitive-loop-if-addr<=-named:  # (payload primitive)
33307     0x11/imm32/alloc-id:fake:payload
33308     0x11/imm32/alloc-id:fake
33309     _string-loop-if-addr<=/imm32/name
33310     0x11/imm32/alloc-id:fake
33311     Single-lit-var/imm32/inouts
33312     0/imm32/no-outputs
33313     0/imm32/no-outputs
33314     0x11/imm32/alloc-id:fake
33315     _string_0f_86_jump_label/imm32/subx-name
33316     0/imm32/no-rm32
33317     0/imm32/no-r32
33318     0/imm32/no-imm32
33319     0/imm32/no-imm8
33320     1/imm32/disp32-is-first-inout
33321     0/imm32/no-xm32
33322     0/imm32/no-x32
33323     0x11/imm32/alloc-id:fake
33324     _Primitive-loop-if-addr>-named/imm32/next
33325 _Primitive-loop-if-addr>-named:  # (payload primitive)
33326     0x11/imm32/alloc-id:fake:payload
33327     0x11/imm32/alloc-id:fake
33328     _string-loop-if-addr>/imm32/name
33329     0x11/imm32/alloc-id:fake
33330     Single-lit-var/imm32/inouts
33331     0/imm32/no-outputs
33332     0/imm32/no-outputs
33333     0x11/imm32/alloc-id:fake
33334     _string_0f_87_jump_label/imm32/subx-name
33335     0/imm32/no-rm32
33336     0/imm32/no-r32
33337     0/imm32/no-imm32
33338     0/imm32/no-imm8
33339     1/imm32/disp32-is-first-inout
33340     0/imm32/no-xm32
33341     0/imm32/no-x32
33342     0x11/imm32/alloc-id:fake
33343     _Primitive-loop-if-<-named/imm32/next
33344 _Primitive-loop-if-<-named:  # (payload primitive)
33345     0x11/imm32/alloc-id:fake:payload
33346     0x11/imm32/alloc-id:fake
33347     _string-loop-if-</imm32/name
33348     0x11/imm32/alloc-id:fake
33349     Single-lit-var/imm32/inouts
33350     0/imm32/no-outputs
33351     0/imm32/no-outputs
33352     0x11/imm32/alloc-id:fake
33353     _string_0f_8c_jump_label/imm32/subx-name
33354     0/imm32/no-rm32
33355     0/imm32/no-r32
33356     0/imm32/no-imm32
33357     0/imm32/no-imm8
33358     1/imm32/disp32-is-first-inout
33359     0/imm32/no-xm32
33360     0/imm32/no-x32
33361     0x11/imm32/alloc-id:fake
33362     _Primitive-loop-if->=-named/imm32/next
33363 _Primitive-loop-if->=-named:  # (payload primitive)
33364     0x11/imm32/alloc-id:fake:payload
33365     0x11/imm32/alloc-id:fake
33366     _string-loop-if->=/imm32/name
33367     0x11/imm32/alloc-id:fake
33368     Single-lit-var/imm32/inouts
33369     0/imm32/no-outputs
33370     0/imm32/no-outputs
33371     0x11/imm32/alloc-id:fake
33372     _string_0f_8d_jump_label/imm32/subx-name
33373     0/imm32/no-rm32
33374     0/imm32/no-r32
33375     0/imm32/no-imm32
33376     0/imm32/no-imm8
33377     1/imm32/disp32-is-first-inout
33378     0/imm32/no-xm32
33379     0/imm32/no-x32
33380     0x11/imm32/alloc-id:fake
33381     _Primitive-loop-if-<=-named/imm32/next
33382 _Primitive-loop-if-<=-named:  # (payload primitive)
33383     0x11/imm32/alloc-id:fake:payload
33384     0x11/imm32/alloc-id:fake
33385     _string-loop-if-<=/imm32/name
33386     0x11/imm32/alloc-id:fake
33387     Single-lit-var/imm32/inouts
33388     0/imm32/no-outputs
33389     0/imm32/no-outputs
33390     0x11/imm32/alloc-id:fake
33391     _string_0f_8e_jump_label/imm32/subx-name
33392     0/imm32/no-rm32
33393     0/imm32/no-r32
33394     0/imm32/no-imm32
33395     0/imm32/no-imm8
33396     1/imm32/disp32-is-first-inout
33397     0/imm32/no-xm32
33398     0/imm32/no-x32
33399     0x11/imm32/alloc-id:fake
33400     _Primitive-loop-if->-named/imm32/next
33401 _Primitive-loop-if->-named:  # (payload primitive)
33402     0x11/imm32/alloc-id:fake:payload
33403     0x11/imm32/alloc-id:fake
33404     _string-loop-if->/imm32/name
33405     0x11/imm32/alloc-id:fake
33406     Single-lit-var/imm32/inouts
33407     0/imm32/no-outputs
33408     0/imm32/no-outputs
33409     0x11/imm32/alloc-id:fake
33410     _string_0f_8f_jump_label/imm32/subx-name
33411     0/imm32/no-rm32
33412     0/imm32/no-r32
33413     0/imm32/no-imm32
33414     0/imm32/no-imm8
33415     1/imm32/disp32-is-first-inout
33416     0/imm32/no-xm32
33417     0/imm32/no-x32
33418     0x11/imm32/alloc-id:fake
33419     _Primitive-loop-named/imm32/next  # we probably don't need an unconditional break
33420 _Primitive-loop-named:  # (payload primitive)
33421     0x11/imm32/alloc-id:fake:payload
33422     0x11/imm32/alloc-id:fake
33423     _string-loop/imm32/name
33424     0x11/imm32/alloc-id:fake
33425     Single-lit-var/imm32/inouts
33426     0/imm32/no-outputs
33427     0/imm32/no-outputs
33428     0x11/imm32/alloc-id:fake
33429     _string_e9_jump_label/imm32/subx-name
33430     0/imm32/no-rm32
33431     0/imm32/no-r32
33432     0/imm32/no-imm32
33433     0/imm32/no-imm8
33434     1/imm32/disp32-is-first-inout
33435     0/imm32/no-xm32
33436     0/imm32/no-x32
33437     0x11/imm32/alloc-id:fake
33438     _Primitive-break-if-float</imm32/next
33439 # - branches based on floating-point comparisons
33440 _Primitive-break-if-float<:  # (payload primitive)
33441     0x11/imm32/alloc-id:fake:payload
33442     0x11/imm32/alloc-id:fake
33443     _string-break-if-float</imm32/name
33444     0/imm32/no-inouts
33445     0/imm32/no-inouts
33446     0/imm32/no-outputs
33447     0/imm32/no-outputs
33448     0x11/imm32/alloc-id:fake
33449     _string_0f_82_jump_break/imm32/subx-name
33450     0/imm32/no-rm32
33451     0/imm32/no-r32
33452     0/imm32/no-imm32
33453     0/imm32/no-imm8
33454     0/imm32/no-disp32
33455     0/imm32/no-xm32
33456     0/imm32/no-x32
33457     0x11/imm32/alloc-id:fake
33458     _Primitive-break-if-float>=/imm32/next
33459 _Primitive-break-if-float>=:  # (payload primitive)
33460     0x11/imm32/alloc-id:fake:payload
33461     0x11/imm32/alloc-id:fake
33462     _string-break-if-float>=/imm32/name
33463     0/imm32/no-inouts
33464     0/imm32/no-inouts
33465     0/imm32/no-outputs
33466     0/imm32/no-outputs
33467     0x11/imm32/alloc-id:fake
33468     _string_0f_83_jump_break/imm32/subx-name
33469     0/imm32/no-rm32
33470     0/imm32/no-r32
33471     0/imm32/no-imm32
33472     0/imm32/no-imm8
33473     0/imm32/no-disp32
33474     0/imm32/no-xm32
33475     0/imm32/no-x32
33476     0x11/imm32/alloc-id:fake
33477     _Primitive-break-if-float<=/imm32/next
33478 _Primitive-break-if-float<=:  # (payload primitive)
33479     0x11/imm32/alloc-id:fake:payload
33480     0x11/imm32/alloc-id:fake
33481     _string-break-if-float<=/imm32/name
33482     0/imm32/no-inouts
33483     0/imm32/no-inouts
33484     0/imm32/no-outputs
33485     0/imm32/no-outputs
33486     0x11/imm32/alloc-id:fake
33487     _string_0f_86_jump_break/imm32/subx-name
33488     0/imm32/no-rm32
33489     0/imm32/no-r32
33490     0/imm32/no-imm32
33491     0/imm32/no-imm8
33492     0/imm32/no-disp32
33493     0/imm32/no-xm32
33494     0/imm32/no-x32
33495     0x11/imm32/alloc-id:fake
33496     _Primitive-break-if-float>/imm32/next
33497 _Primitive-break-if-float>:  # (payload primitive)
33498     0x11/imm32/alloc-id:fake:payload
33499     0x11/imm32/alloc-id:fake
33500     _string-break-if-float>/imm32/name
33501     0/imm32/no-inouts
33502     0/imm32/no-inouts
33503     0/imm32/no-outputs
33504     0/imm32/no-outputs
33505     0x11/imm32/alloc-id:fake
33506     _string_0f_87_jump_break/imm32/subx-name
33507     0/imm32/no-rm32
33508     0/imm32/no-r32
33509     0/imm32/no-imm32
33510     0/imm32/no-imm8
33511     0/imm32/no-disp32
33512     0/imm32/no-xm32
33513     0/imm32/no-x32
33514     0x11/imm32/alloc-id:fake
33515     _Primitive-loop-if-float</imm32/next
33516 _Primitive-loop-if-float<:  # (payload primitive)
33517     0x11/imm32/alloc-id:fake:payload
33518     0x11/imm32/alloc-id:fake
33519     _string-loop-if-float</imm32/name
33520     0/imm32/no-inouts
33521     0/imm32/no-inouts
33522     0/imm32/no-outputs
33523     0/imm32/no-outputs
33524     0x11/imm32/alloc-id:fake
33525     _string_0f_82_jump_loop/imm32/subx-name
33526     0/imm32/no-rm32
33527     0/imm32/no-r32
33528     0/imm32/no-imm32
33529     0/imm32/no-imm8
33530     0/imm32/no-disp32
33531     0/imm32/no-xm32
33532     0/imm32/no-x32
33533     0x11/imm32/alloc-id:fake
33534     _Primitive-loop-if-float>=/imm32/next
33535 _Primitive-loop-if-float>=:  # (payload primitive)
33536     0x11/imm32/alloc-id:fake:payload
33537     0x11/imm32/alloc-id:fake
33538     _string-loop-if-float>=/imm32/name
33539     0/imm32/no-inouts
33540     0/imm32/no-inouts
33541     0/imm32/no-outputs
33542     0/imm32/no-outputs
33543     0x11/imm32/alloc-id:fake
33544     _string_0f_83_jump_loop/imm32/subx-name
33545     0/imm32/no-rm32
33546     0/imm32/no-r32
33547     0/imm32/no-imm32
33548     0/imm32/no-imm8
33549     0/imm32/no-disp32
33550     0/imm32/no-xm32
33551     0/imm32/no-x32
33552     0x11/imm32/alloc-id:fake
33553     _Primitive-loop-if-float<=/imm32/next
33554 _Primitive-loop-if-float<=:  # (payload primitive)
33555     0x11/imm32/alloc-id:fake:payload
33556     0x11/imm32/alloc-id:fake
33557     _string-loop-if-float<=/imm32/name
33558     0/imm32/no-inouts
33559     0/imm32/no-inouts
33560     0/imm32/no-outputs
33561     0/imm32/no-outputs
33562     0x11/imm32/alloc-id:fake
33563     _string_0f_86_jump_loop/imm32/subx-name
33564     0/imm32/no-rm32
33565     0/imm32/no-r32
33566     0/imm32/no-imm32
33567     0/imm32/no-imm8
33568     0/imm32/no-disp32
33569     0/imm32/no-xm32
33570     0/imm32/no-x32
33571     0x11/imm32/alloc-id:fake
33572     _Primitive-loop-if-float>/imm32/next
33573 _Primitive-loop-if-float>:  # (payload primitive)
33574     0x11/imm32/alloc-id:fake:payload
33575     0x11/imm32/alloc-id:fake
33576     _string-loop-if-float>/imm32/name
33577     0/imm32/no-inouts
33578     0/imm32/no-inouts
33579     0/imm32/no-outputs
33580     0/imm32/no-outputs
33581     0x11/imm32/alloc-id:fake
33582     _string_0f_87_jump_loop/imm32/subx-name
33583     0/imm32/no-rm32
33584     0/imm32/no-r32
33585     0/imm32/no-imm32
33586     0/imm32/no-imm8
33587     0/imm32/no-disp32
33588     0/imm32/no-xm32
33589     0/imm32/no-x32
33590     0x11/imm32/alloc-id:fake
33591     _Primitive-break-if-float<-named/imm32/next
33592 _Primitive-break-if-float<-named:  # (payload primitive)
33593     0x11/imm32/alloc-id:fake:payload
33594     0x11/imm32/alloc-id:fake
33595     _string-break-if-float</imm32/name
33596     0x11/imm32/alloc-id:fake
33597     Single-lit-var/imm32/inouts
33598     0/imm32/no-outputs
33599     0/imm32/no-outputs
33600     0x11/imm32/alloc-id:fake
33601     _string_0f_82_jump_label/imm32/subx-name
33602     0/imm32/no-rm32
33603     0/imm32/no-r32
33604     0/imm32/no-imm32
33605     0/imm32/no-imm8
33606     1/imm32/disp32-is-first-inout
33607     0/imm32/no-xm32
33608     0/imm32/no-x32
33609     0x11/imm32/alloc-id:fake
33610     _Primitive-break-if-float>=-named/imm32/next
33611 _Primitive-break-if-float>=-named:  # (payload primitive)
33612     0x11/imm32/alloc-id:fake:payload
33613     0x11/imm32/alloc-id:fake
33614     _string-break-if-float>=/imm32/name
33615     0x11/imm32/alloc-id:fake
33616     Single-lit-var/imm32/inouts
33617     0/imm32/no-outputs
33618     0/imm32/no-outputs
33619     0x11/imm32/alloc-id:fake
33620     _string_0f_83_jump_label/imm32/subx-name
33621     0/imm32/no-rm32
33622     0/imm32/no-r32
33623     0/imm32/no-imm32
33624     0/imm32/no-imm8
33625     1/imm32/disp32-is-first-inout
33626     0/imm32/no-xm32
33627     0/imm32/no-x32
33628     0x11/imm32/alloc-id:fake
33629     _Primitive-break-if-float<=-named/imm32/next
33630 _Primitive-break-if-float<=-named:  # (payload primitive)
33631     0x11/imm32/alloc-id:fake:payload
33632     0x11/imm32/alloc-id:fake
33633     _string-break-if-float<=/imm32/name
33634     0x11/imm32/alloc-id:fake
33635     Single-lit-var/imm32/inouts
33636     0/imm32/no-outputs
33637     0/imm32/no-outputs
33638     0x11/imm32/alloc-id:fake
33639     _string_0f_86_jump_label/imm32/subx-name
33640     0/imm32/no-rm32
33641     0/imm32/no-r32
33642     0/imm32/no-imm32
33643     0/imm32/no-imm8
33644     1/imm32/disp32-is-first-inout
33645     0/imm32/no-xm32
33646     0/imm32/no-x32
33647     0x11/imm32/alloc-id:fake
33648     _Primitive-break-if-float>-named/imm32/next
33649 _Primitive-break-if-float>-named:  # (payload primitive)
33650     0x11/imm32/alloc-id:fake:payload
33651     0x11/imm32/alloc-id:fake
33652     _string-break-if-float>/imm32/name
33653     0x11/imm32/alloc-id:fake
33654     Single-lit-var/imm32/inouts
33655     0/imm32/no-outputs
33656     0/imm32/no-outputs
33657     0x11/imm32/alloc-id:fake
33658     _string_0f_87_jump_label/imm32/subx-name
33659     0/imm32/no-rm32
33660     0/imm32/no-r32
33661     0/imm32/no-imm32
33662     0/imm32/no-imm8
33663     1/imm32/disp32-is-first-inout
33664     0/imm32/no-xm32
33665     0/imm32/no-x32
33666     0x11/imm32/alloc-id:fake
33667     _Primitive-loop-if-float<-named/imm32/next
33668 _Primitive-loop-if-float<-named:  # (payload primitive)
33669     0x11/imm32/alloc-id:fake:payload
33670     0x11/imm32/alloc-id:fake
33671     _string-loop-if-float</imm32/name
33672     0x11/imm32/alloc-id:fake
33673     Single-lit-var/imm32/inouts
33674     0/imm32/no-outputs
33675     0/imm32/no-outputs
33676     0x11/imm32/alloc-id:fake
33677     _string_0f_82_jump_label/imm32/subx-name
33678     0/imm32/no-rm32
33679     0/imm32/no-r32
33680     0/imm32/no-imm32
33681     0/imm32/no-imm8
33682     1/imm32/disp32-is-first-inout
33683     0/imm32/no-xm32
33684     0/imm32/no-x32
33685     0x11/imm32/alloc-id:fake
33686     _Primitive-loop-if-float>=-named/imm32/next
33687 _Primitive-loop-if-float>=-named:  # (payload primitive)
33688     0x11/imm32/alloc-id:fake:payload
33689     0x11/imm32/alloc-id:fake
33690     _string-loop-if-float>=/imm32/name
33691     0x11/imm32/alloc-id:fake
33692     Single-lit-var/imm32/inouts
33693     0/imm32/no-outputs
33694     0/imm32/no-outputs
33695     0x11/imm32/alloc-id:fake
33696     _string_0f_83_jump_label/imm32/subx-name
33697     0/imm32/no-rm32
33698     0/imm32/no-r32
33699     0/imm32/no-imm32
33700     0/imm32/no-imm8
33701     1/imm32/disp32-is-first-inout
33702     0/imm32/no-xm32
33703     0/imm32/no-x32
33704     0x11/imm32/alloc-id:fake
33705     _Primitive-loop-if-float<=-named/imm32/next
33706 _Primitive-loop-if-float<=-named:  # (payload primitive)
33707     0x11/imm32/alloc-id:fake:payload
33708     0x11/imm32/alloc-id:fake
33709     _string-loop-if-float<=/imm32/name
33710     0x11/imm32/alloc-id:fake
33711     Single-lit-var/imm32/inouts
33712     0/imm32/no-outputs
33713     0/imm32/no-outputs
33714     0x11/imm32/alloc-id:fake
33715     _string_0f_86_jump_label/imm32/subx-name
33716     0/imm32/no-rm32
33717     0/imm32/no-r32
33718     0/imm32/no-imm32
33719     0/imm32/no-imm8
33720     1/imm32/disp32-is-first-inout
33721     0/imm32/no-xm32
33722     0/imm32/no-x32
33723     0x11/imm32/alloc-id:fake
33724     _Primitive-loop-if-float>-named/imm32/next
33725 _Primitive-loop-if-float>-named:  # (payload primitive)
33726     0x11/imm32/alloc-id:fake:payload
33727     0x11/imm32/alloc-id:fake
33728     _string-loop-if-float>/imm32/name
33729     0x11/imm32/alloc-id:fake
33730     Single-lit-var/imm32/inouts
33731     0/imm32/no-outputs
33732     0/imm32/no-outputs
33733     0x11/imm32/alloc-id:fake
33734     _string_0f_87_jump_label/imm32/subx-name
33735     0/imm32/no-rm32
33736     0/imm32/no-r32
33737     0/imm32/no-imm32
33738     0/imm32/no-imm8
33739     1/imm32/disp32-is-first-inout
33740     0/imm32/no-xm32
33741     0/imm32/no-x32
33742     0/imm32/next
33743     0/imm32/next
33744 
33745 # string literals for Mu instructions
33746 _string-add:  # (payload array byte)
33747     0x11/imm32/alloc-id:fake:payload
33748     # "add"
33749     0x3/imm32/size
33750     0x61/a 0x64/d 0x64/d
33751 _string-address:  # (payload array byte)
33752     0x11/imm32/alloc-id:fake:payload
33753     # "address"
33754     0x7/imm32/size
33755     0x61/a 0x64/d 0x64/d 0x72/r 0x65/e 0x73/s 0x73/s
33756 _string-add-to:  # (payload array byte)
33757     0x11/imm32/alloc-id:fake:payload
33758     # "add-to"
33759     0x6/imm32/size
33760     0x61/a 0x64/d 0x64/d 0x2d/dash 0x74/t 0x6f/o
33761 _string-and:  # (payload array byte)
33762     0x11/imm32/alloc-id:fake:payload
33763     # "and"
33764     0x3/imm32/size
33765     0x61/a 0x6e/n 0x64/d
33766 _string-and-with:  # (payload array byte)
33767     0x11/imm32/alloc-id:fake:payload
33768     # "and-with"
33769     0x8/imm32/size
33770     0x61/a 0x6e/n 0x64/d 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
33771 _string-break:  # (payload array byte)
33772     0x11/imm32/alloc-id:fake:payload
33773     # "break"
33774     0x5/imm32/size
33775     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k
33776 _string-break-if-<:  # (payload array byte)
33777     0x11/imm32/alloc-id:fake:payload
33778     # "break-if-<"
33779     0xa/imm32/size
33780     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/<
33781 _string-break-if-<=:  # (payload array byte)
33782     0x11/imm32/alloc-id:fake:payload
33783     # "break-if-<="
33784     0xb/imm32/size
33785     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< 0x3d/=
33786 _string-break-if-=:  # (payload array byte)
33787     0x11/imm32/alloc-id:fake:payload
33788     # "break-if-="
33789     0xa/imm32/size
33790     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3d/=
33791 _string-break-if->:  # (payload array byte)
33792     0x11/imm32/alloc-id:fake:payload
33793     # "break-if->"
33794     0xa/imm32/size
33795     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/>
33796 _string-break-if->=:  # (payload array byte)
33797     0x11/imm32/alloc-id:fake:payload
33798     # "break-if->="
33799     0xb/imm32/size
33800     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> 0x3d/=
33801 _string-break-if-!=:  # (payload array byte)
33802     0x11/imm32/alloc-id:fake:payload
33803     # "break-if-!="
33804     0xb/imm32/size
33805     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x21/! 0x3d/=
33806 _string-break-if-addr<:  # (payload array byte)
33807     0x11/imm32/alloc-id:fake:payload
33808     # "break-if-addr<"
33809     0xe/imm32/size
33810     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/<
33811 _string-break-if-addr<=:  # (payload array byte)
33812     0x11/imm32/alloc-id:fake:payload
33813     # "break-if-addr<="
33814     0xf/imm32/size
33815     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/=
33816 _string-break-if-addr>:  # (payload array byte)
33817     0x11/imm32/alloc-id:fake:payload
33818     # "break-if-addr>"
33819     0xe/imm32/size
33820     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/>
33821 _string-break-if-addr>=:  # (payload array byte)
33822     0x11/imm32/alloc-id:fake:payload
33823     # "break-if-addr>="
33824     0xf/imm32/size
33825     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/=
33826 _string-break-if-float<:  # (payload array byte)
33827     0x11/imm32/alloc-id:fake:payload
33828     # "break-if-float<"
33829     0xf/imm32/size
33830     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/<
33831 _string-break-if-float<=:  # (payload array byte)
33832     0x11/imm32/alloc-id:fake:payload
33833     # "break-if-float<="
33834     0x10/imm32/size
33835     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/=
33836 _string-break-if-float>:  # (payload array byte)
33837     0x11/imm32/alloc-id:fake:payload
33838     # "break-if-float>"
33839     0xf/imm32/size
33840     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/>
33841 _string-break-if-float>=:  # (payload array byte)
33842     0x11/imm32/alloc-id:fake:payload
33843     # "break-if-float>="
33844     0x10/imm32/size
33845     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/=
33846 _string-compare:  # (payload array byte)
33847     0x11/imm32/alloc-id:fake:payload
33848     # "compare"
33849     0x7/imm32/size
33850     0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e
33851 _string-copy:  # (payload array byte)
33852     0x11/imm32/alloc-id:fake:payload
33853     # "copy"
33854     0x4/imm32/size
33855     0x63/c 0x6f/o 0x70/p 0x79/y
33856 _string-copy-to:  # (payload array byte)
33857     0x11/imm32/alloc-id:fake:payload
33858     # "copy-to"
33859     0x7/imm32/size
33860     0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/dash 0x74/t 0x6f/o
33861 _string-copy-byte:
33862     0x11/imm32/alloc-id:fake:payload
33863     # "copy-byte"
33864     0x9/imm32/size
33865     0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/- 0x62/b 0x79/y 0x74/t 0x65/e
33866 _string-copy-byte-to:
33867     0x11/imm32/alloc-id:fake:payload
33868     # "copy-byte-to"
33869     0xc/imm32/size
33870     0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/- 0x62/b 0x79/y 0x74/t 0x65/e 0x2d/- 0x74/t 0x6f/o
33871 _string-decrement:  # (payload array byte)
33872     0x11/imm32/alloc-id:fake:payload
33873     # "decrement"
33874     0x9/imm32/size
33875     0x64/d 0x65/e 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t
33876 _string-increment:  # (payload array byte)
33877     0x11/imm32/alloc-id:fake:payload
33878     # "increment"
33879     0x9/imm32/size
33880     0x69/i 0x6e/n 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t
33881 _string-loop:  # (payload array byte)
33882     0x11/imm32/alloc-id:fake:payload
33883     # "loop"
33884     0x4/imm32/size
33885     0x6c/l 0x6f/o 0x6f/o 0x70/p
33886 _string-loop-if-<:  # (payload array byte)
33887     0x11/imm32/alloc-id:fake:payload
33888     # "loop-if-<"
33889     0x9/imm32/size
33890     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/<
33891 _string-loop-if-<=:  # (payload array byte)
33892     0x11/imm32/alloc-id:fake:payload
33893     # "loop-if-<="
33894     0xa/imm32/size
33895     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< 0x3d/=
33896 _string-loop-if-=:  # (payload array byte)
33897     0x11/imm32/alloc-id:fake:payload
33898     # "loop-if-="
33899     0x9/imm32/size
33900     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3d/=
33901 _string-loop-if->:  # (payload array byte)
33902     0x11/imm32/alloc-id:fake:payload
33903     # "loop-if->"
33904     0x9/imm32/size
33905     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/>
33906 _string-loop-if->=:  # (payload array byte)
33907     0x11/imm32/alloc-id:fake:payload
33908     # "loop-if->="
33909     0xa/imm32/size
33910     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> 0x3d/=
33911 _string-loop-if-!=:  # (payload array byte)
33912     0x11/imm32/alloc-id:fake:payload
33913     # "loop-if-!="
33914     0xa/imm32/size
33915     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x21/! 0x3d/=
33916 _string-loop-if-addr<:  # (payload array byte)
33917     0x11/imm32/alloc-id:fake:payload
33918     # "loop-if-addr<"
33919     0xd/imm32/size
33920     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/<
33921 _string-loop-if-addr<=:  # (payload array byte)
33922     0x11/imm32/alloc-id:fake:payload
33923     # "loop-if-addr<="
33924     0xe/imm32/size
33925     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/=
33926 _string-loop-if-addr>:  # (payload array byte)
33927     0x11/imm32/alloc-id:fake:payload
33928     # "loop-if-addr>"
33929     0xd/imm32/size
33930     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/>
33931 _string-loop-if-addr>=:  # (payload array byte)
33932     0x11/imm32/alloc-id:fake:payload
33933     # "loop-if-addr>="
33934     0xe/imm32/size
33935     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/=
33936 _string-loop-if-float<:  # (payload array byte)
33937     0x11/imm32/alloc-id:fake:payload
33938     # "loop-if-float<"
33939     0xe/imm32/size
33940     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/<
33941 _string-loop-if-float<=:  # (payload array byte)
33942     0x11/imm32/alloc-id:fake:payload
33943     # "loop-if-float<="
33944     0xf/imm32/size
33945     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/=
33946 _string-loop-if-float>:  # (payload array byte)
33947     0x11/imm32/alloc-id:fake:payload
33948     # "loop-if-float>"
33949     0xe/imm32/size
33950     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/>
33951 _string-loop-if-float>=:  # (payload array byte)
33952     0x11/imm32/alloc-id:fake:payload
33953     # "loop-if-float>="
33954     0xf/imm32/size
33955     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/=
33956 _string-multiply:  # (payload array byte)
33957     0x11/imm32/alloc-id:fake:payload
33958     # "multiply"
33959     0x8/imm32/size
33960     0x6d/m 0x75/u 0x6c/l 0x74/t 0x69/i 0x70/p 0x6c/l 0x79/y
33961 _string-convert:  # (payload array byte)
33962     0x11/imm32/alloc-id:fake:payload
33963     # "convert"
33964     0x7/imm32/size
33965     0x63/c 0x6f/o 0x6e/n 0x76/v 0x65/e 0x72/r 0x74/t
33966 _string-truncate:  # (payload array byte)
33967     0x11/imm32/alloc-id:fake:payload
33968     # "truncate"
33969     0x8/imm32/size
33970     0x74/t 0x72/r 0x75/u 0x6e/n 0x63/c 0x61/a 0x74/t 0x65/e
33971 _string-reinterpret:  # (payload array byte)
33972     0x11/imm32/alloc-id:fake:payload
33973     # "reinterpret"
33974     0xb/imm32/size
33975     0x72/r 0x65/e 0x69/i 0x6e/n 0x74/t 0x65/e 0x72/r 0x70/p 0x72/r 0x65/e 0x74/t
33976 _string-divide:
33977     0x11/imm32/alloc-id:fake:payload
33978     # "divide"
33979     0x6/imm32/size
33980     0x64/d 0x69/i 0x76/v 0x69/i 0x64/d 0x65/e
33981 _string-max:
33982     0x11/imm32/alloc-id:fake:payload
33983     # "max"
33984     0x3/imm32/size
33985     0x6d/m 0x61/a 0x78/x
33986 _string-min:
33987     0x11/imm32/alloc-id:fake:payload
33988     # "min"
33989     0x3/imm32/size
33990     0x6d/m 0x69/i 0x6e/n
33991 _string-reciprocal:
33992     0x11/imm32/alloc-id:fake:payload
33993     # "reciprocal"
33994     0xa/imm32/size
33995     0x72/r 0x65/e 0x63/c 0x69/i 0x70/p 0x72/r 0x6f/o 0x63/c 0x61/a 0x6c/l
33996 _string-square-root:
33997     0x11/imm32/alloc-id:fake:payload
33998     # "square-root"
33999     0xb/imm32/size
34000     0x73/s 0x71/q 0x75/u 0x61/a 0x72/r 0x65/e 0x2d/- 0x72/r 0x6f/o 0x6f/o 0x74/t
34001 _string-inverse-square-root:
34002     0x11/imm32/alloc-id:fake:payload
34003     # "inverse-square-root"
34004     0x13/imm32/size
34005     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
34006 _string-negate:  # (payload array byte)
34007     0x11/imm32/alloc-id:fake:payload
34008     # "negate"
34009     0x6/imm32/size
34010     0x6e/n 0x65/e 0x67/g 0x61/a 0x74/t 0x65/e
34011 _string-or:  # (payload array byte)
34012     0x11/imm32/alloc-id:fake:payload
34013     # "or"
34014     0x2/imm32/size
34015     0x6f/o 0x72/r
34016 _string-or-with:  # (payload array byte)
34017     0x11/imm32/alloc-id:fake:payload
34018     # "or-with"
34019     0x7/imm32/size
34020     0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
34021 _string-subtract:  # (payload array byte)
34022     0x11/imm32/alloc-id:fake:payload
34023     # "subtract"
34024     0x8/imm32/size
34025     0x73/s 0x75/u 0x62/b 0x74/t 0x72/r 0x61/a 0x63/c 0x74/t
34026 _string-subtract-from:  # (payload array byte)
34027     0x11/imm32/alloc-id:fake:payload
34028     # "subtract-from"
34029     0xd/imm32/size
34030     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
34031 _string-xor:  # (payload array byte)
34032     0x11/imm32/alloc-id:fake:payload
34033     # "xor"
34034     0x3/imm32/size
34035     0x78/x 0x6f/o 0x72/r
34036 _string-xor-with:  # (payload array byte)
34037     0x11/imm32/alloc-id:fake:payload
34038     # "xor-with"
34039     0x8/imm32/size
34040     0x78/x 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
34041 _string-shift-left:  # (payload array byte)
34042     0x11/imm32/alloc-id:fake:payload
34043     # "shift-left"
34044     0xa/imm32/size
34045     0x73/s 0x68/h 0x69/i 0x66/f 0x74/t 0x2d/dash 0x6c/l 0x65/e 0x66/f 0x74/t
34046 _string-shift-right:  # (payload array byte)
34047     0x11/imm32/alloc-id:fake:payload
34048     # "shift-right"
34049     0xb/imm32/size
34050     0x73/s 0x68/h 0x69/i 0x66/f 0x74/t 0x2d/dash 0x72/r 0x69/i 0x67/g 0x68/h 0x74/t
34051 _string-shift-right-signed:  # (payload array byte)
34052     0x11/imm32/alloc-id:fake:payload
34053     # "shift-right-signed"
34054     0x12/imm32/size
34055     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
34056 
34057 # string literals for SubX instructions
34058 _string_01_add_to:  # (payload array byte)
34059     0x11/imm32/alloc-id:fake:payload
34060     # "01/add-to"
34061     0x9/imm32/size
34062     0x30/0 0x31/1 0x2f/slash 0x61/a 0x64/d 0x64/d 0x2d/dash 0x74/t 0x6f/o
34063 _string_03_add:  # (payload array byte)
34064     0x11/imm32/alloc-id:fake:payload
34065     # "03/add"
34066     0x6/imm32/size
34067     0x30/0 0x33/3 0x2f/slash 0x61/a 0x64/d 0x64/d
34068 _string_05_add_to_eax:  # (payload array byte)
34069     0x11/imm32/alloc-id:fake:payload
34070     # "05/add-to-eax"
34071     0xd/imm32/size
34072     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
34073 _string_09_or_with:  # (payload array byte)
34074     0x11/imm32/alloc-id:fake:payload
34075     # "09/or-with"
34076     0xa/imm32/size
34077     0x30/0 0x39/9 0x2f/slash 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
34078 _string_0b_or:  # (payload array byte)
34079     0x11/imm32/alloc-id:fake:payload
34080     # "0b/or"
34081     0x5/imm32/size
34082     0x30/0 0x62/b 0x2f/slash 0x6f/o 0x72/r
34083 _string_0d_or_with_eax:  # (payload array byte)
34084     0x11/imm32/alloc-id:fake:payload
34085     # "0d/or-with-eax"
34086     0xe/imm32/size
34087     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
34088 _string_0f_82_jump_label:  # (payload array byte)
34089     0x11/imm32/alloc-id:fake:payload
34090     # "0f 82/jump-if-addr<"
34091     0x13/imm32/size
34092     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/<
34093 _string_0f_82_jump_break:  # (payload array byte)
34094     0x11/imm32/alloc-id:fake:payload
34095     # "0f 82/jump-if-addr< break/disp32"
34096     0x20/imm32/size
34097     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
34098 _string_0f_82_jump_loop:  # (payload array byte)
34099     0x11/imm32/alloc-id:fake:payload
34100     # "0f 82/jump-if-addr< loop/disp32"
34101     0x1f/imm32/size
34102     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
34103 _string_0f_83_jump_label:  # (payload array byte)
34104     0x11/imm32/alloc-id:fake:payload
34105     # "0f 83/jump-if-addr>="
34106     0x14/imm32/size
34107     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/=
34108 _string_0f_83_jump_break:  # (payload array byte)
34109     0x11/imm32/alloc-id:fake:payload
34110     # "0f 83/jump-if-addr>= break/disp32"
34111     0x21/imm32/size
34112     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
34113 _string_0f_83_jump_loop:  # (payload array byte)
34114     0x11/imm32/alloc-id:fake:payload
34115     # "0f 83/jump-if-addr>= loop/disp32"
34116     0x20/imm32/size
34117     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
34118 _string_0f_84_jump_label:  # (payload array byte)
34119     0x11/imm32/alloc-id:fake:payload
34120     # "0f 84/jump-if-="
34121     0xf/imm32/size
34122     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/=
34123 _string_0f_84_jump_break:  # (payload array byte)
34124     0x11/imm32/alloc-id:fake:payload
34125     # "0f 84/jump-if-= break/disp32"
34126     0x1c/imm32/size
34127     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
34128 _string_0f_84_jump_loop:  # (payload array byte)
34129     0x11/imm32/alloc-id:fake:payload
34130     # "0f 84/jump-if-= loop/disp32"
34131     0x1b/imm32/size
34132     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
34133 _string_0f_85_jump_label:  # (payload array byte)
34134     0x11/imm32/alloc-id:fake:payload
34135     # "0f 85/jump-if-!="
34136     0x10/imm32/size
34137     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/=
34138 _string_0f_85_jump_break:  # (payload array byte)
34139     0x11/imm32/alloc-id:fake:payload
34140     # "0f 85/jump-if-!= break/disp32"
34141     0x1d/imm32/size
34142     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
34143 _string_0f_85_jump_loop:  # (payload array byte)
34144     0x11/imm32/alloc-id:fake:payload
34145     # "0f 85/jump-if-!= loop/disp32"
34146     0x1c/imm32/size
34147     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
34148 _string_0f_86_jump_label:  # (payload array byte)
34149     0x11/imm32/alloc-id:fake:payload
34150     # "0f 86/jump-if-addr<="
34151     0x14/imm32/size
34152     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/=
34153 _string_0f_86_jump_break:  # (payload array byte)
34154     0x11/imm32/alloc-id:fake:payload
34155     # "0f 86/jump-if-addr<= break/disp32"
34156     0x21/imm32/size
34157     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
34158 _string_0f_86_jump_loop:  # (payload array byte)
34159     0x11/imm32/alloc-id:fake:payload
34160     # "0f 86/jump-if-addr<= loop/disp32"
34161     0x20/imm32/size
34162     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
34163 _string_0f_87_jump_label:  # (payload array byte)
34164     0x11/imm32/alloc-id:fake:payload
34165     # "0f 87/jump-if-addr>"
34166     0x13/imm32/size
34167     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/>
34168 _string_0f_87_jump_break:  # (payload array byte)
34169     0x11/imm32/alloc-id:fake:payload
34170     # "0f 87/jump-if-addr> break/disp32"
34171     0x20/imm32/size
34172     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
34173 _string_0f_87_jump_loop:  # (payload array byte)
34174     0x11/imm32/alloc-id:fake:payload
34175     # "0f 87/jump-if-addr> loop/disp32"
34176     0x1f/imm32/size
34177     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
34178 _string_0f_8c_jump_label:  # (payload array byte)
34179     0x11/imm32/alloc-id:fake:payload
34180     # "0f 8c/jump-if-<"
34181     0xf/imm32/size
34182     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/<
34183 _string_0f_8c_jump_break:  # (payload array byte)
34184     0x11/imm32/alloc-id:fake:payload
34185     # "0f 8c/jump-if-< break/disp32"
34186     0x1c/imm32/size
34187     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
34188 _string_0f_8c_jump_loop:  # (payload array byte)
34189     0x11/imm32/alloc-id:fake:payload
34190     # "0f 8c/jump-if-< loop/disp32"
34191     0x1b/imm32/size
34192     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
34193 _string_0f_8d_jump_label:  # (payload array byte)
34194     0x11/imm32/alloc-id:fake:payload
34195     # "0f 8d/jump-if->="
34196     0x10/imm32/size
34197     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/=
34198 _string_0f_8d_jump_break:  # (payload array byte)
34199     0x11/imm32/alloc-id:fake:payload
34200     # "0f 8d/jump-if->= break/disp32"
34201     0x1d/imm32/size
34202     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
34203 _string_0f_8d_jump_loop:  # (payload array byte)
34204     0x11/imm32/alloc-id:fake:payload
34205     # "0f 8d/jump-if->= loop/disp32"
34206     0x1c/imm32/size
34207     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
34208 _string_0f_8e_jump_label:  # (payload array byte)
34209     0x11/imm32/alloc-id:fake:payload
34210     # "0f 8e/jump-if-<="
34211     0x10/imm32/size
34212     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/=
34213 _string_0f_8e_jump_break:  # (payload array byte)
34214     0x11/imm32/alloc-id:fake:payload
34215     # "0f 8e/jump-if-<= break/disp32"
34216     0x1d/imm32/size
34217     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
34218 _string_0f_8e_jump_loop:  # (payload array byte)
34219     0x11/imm32/alloc-id:fake:payload
34220     # "0f 8e/jump-if-<= loop/disp32"
34221     0x1c/imm32/size
34222     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
34223 _string_0f_8f_jump_label:  # (payload array byte)
34224     0x11/imm32/alloc-id:fake:payload
34225     # "0f 8f/jump-if->"
34226     0xf/imm32/size
34227     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/>
34228 _string_0f_8f_jump_break:  # (payload array byte)
34229     0x11/imm32/alloc-id:fake:payload
34230     # "0f 8f/jump-if-> break/disp32"
34231     0x1c/imm32/size
34232     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
34233 _string_0f_8f_jump_loop:  # (payload array byte)
34234     0x11/imm32/alloc-id:fake:payload
34235     # "0f 8f/jump-if-> loop/disp32"
34236     0x1b/imm32/size
34237     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
34238 _string_0f_af_multiply:  # (payload array byte)
34239     0x11/imm32/alloc-id:fake:payload
34240     # "0f af/multiply"
34241     0xe/imm32/size
34242     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
34243 _string_f3_0f_2a_convert_to_float:
34244     0x11/imm32/alloc-id:fake:payload
34245     # "f3 0f 2a/convert-to-float"
34246     0x19/imm32/size
34247     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
34248 _string_f3_0f_2d_convert_to_int:
34249     0x11/imm32/alloc-id:fake:payload
34250     # "f3 0f 2d/convert-to-int"
34251     0x17/imm32/size
34252     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
34253 _string_f3_0f_2c_truncate_to_int:
34254     0x11/imm32/alloc-id:fake:payload
34255     # "f3 0f 2c/truncate-to-int"
34256     0x18/imm32/size
34257     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
34258 _string_f3_0f_58_add:
34259     0x11/imm32/alloc-id:fake:payload
34260     # "f3 0f 58/add"
34261     0xc/imm32/size
34262     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x38/8 0x2f/slash 0x61/a 0x64/d 0x64/d
34263 _string_f3_0f_5c_subtract:
34264     0x11/imm32/alloc-id:fake:payload
34265     # "f3 0f 5c/subtract"
34266     0x11/imm32/size
34267     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
34268 _string_f3_0f_59_multiply:
34269     0x11/imm32/alloc-id:fake:payload
34270     # "f3 0f 59/multiply"
34271     0x11/imm32/size
34272     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
34273 _string_f3_0f_5e_divide:
34274     0x11/imm32/alloc-id:fake:payload
34275     # "f3 0f 5e/divide"
34276     0xf/imm32/size
34277     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
34278 _string_f3_0f_53_reciprocal:
34279     0x11/imm32/alloc-id:fake:payload
34280     # "f3 0f 53/reciprocal"
34281     0x13/imm32/size
34282     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
34283 _string_f3_0f_51_square_root:
34284     0x11/imm32/alloc-id:fake:payload
34285     # "f3 0f 51/square-root"
34286     0x14/imm32/size
34287     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
34288 _string_f3_0f_52_inverse_square_root:
34289     0x11/imm32/alloc-id:fake:payload
34290     # "f3 0f 52/inverse-square-root"
34291     0x1c/imm32/size
34292     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
34293 _string_f3_0f_5d_min:
34294     0x11/imm32/alloc-id:fake:payload
34295     # "f3 0f 5d/min"
34296     0xc/imm32/size
34297     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x64/d 0x2f/slash 0x6d/m 0x69/i 0x6e/n
34298 _string_f3_0f_5f_max:
34299     0x11/imm32/alloc-id:fake:payload
34300     # "f3 0f 5f/max"
34301     0xc/imm32/size
34302     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x66/f 0x2f/slash 0x6d/m 0x61/a 0x78/x
34303 _string_f3_0f_10_copy:
34304     0x11/imm32/alloc-id:fake:payload
34305     # "f3 0f 10/copy"
34306     0xd/imm32/size
34307     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
34308 _string_f3_0f_11_copy:
34309     0x11/imm32/alloc-id:fake:payload
34310     # "f3 0f 11/copy"
34311     0xd/imm32/size
34312     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
34313 _string_0f_2f_compare:
34314     0x11/imm32/alloc-id:fake:payload
34315     # "0f 2f/compare"
34316     0xd/imm32/size
34317     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
34318 _string_21_and_with:  # (payload array byte)
34319     0x11/imm32/alloc-id:fake:payload
34320     # "21/and-with"
34321     0xb/imm32/size
34322     0x32/2 0x31/1 0x2f/slash 0x61/a 0x6e/n 0x64/d 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
34323 _string_23_and:  # (payload array byte)
34324     0x11/imm32/alloc-id:fake:payload
34325     # "23/and"
34326     0x6/imm32/size
34327     0x32/2 0x33/3 0x2f/slash 0x61/a 0x6e/n 0x64/d
34328 _string_25_and_with_eax:  # (payload array byte)
34329     0x11/imm32/alloc-id:fake:payload
34330     # "25/and-with-eax"
34331     0xf/imm32/size
34332     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
34333 _string_29_subtract_from:  # (payload array byte)
34334     0x11/imm32/alloc-id:fake:payload
34335     # "29/subtract-from"
34336     0x10/imm32/size
34337     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
34338 _string_2b_subtract:  # (payload array byte)
34339     0x11/imm32/alloc-id:fake:payload
34340     # "2b/subtract"
34341     0xb/imm32/size
34342     0x32/2 0x62/b 0x2f/slash 0x73/s 0x75/u 0x62/b 0x74/t 0x72/r 0x61/a 0x63/c 0x74/t
34343 _string_2d_subtract_from_eax:  # (payload array byte)
34344     0x11/imm32/alloc-id:fake:payload
34345     # "2d/subtract-from-eax"
34346     0x14/imm32/size
34347     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
34348 _string_31_xor_with:  # (payload array byte)
34349     0x11/imm32/alloc-id:fake:payload
34350     # "31/xor-with"
34351     0xb/imm32/size
34352     0x33/3 0x31/1 0x2f/slash 0x78/x 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
34353 _string_33_xor:  # (payload array byte)
34354     0x11/imm32/alloc-id:fake:payload
34355     # "33/xor"
34356     0x6/imm32/size
34357     0x33/3 0x33/3 0x2f/slash 0x78/x 0x6f/o 0x72/r
34358 _string_35_xor_with_eax:  # (payload array byte)
34359     0x11/imm32/alloc-id:fake:payload
34360     # "35/xor-with-eax"
34361     0xf/imm32/size
34362     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
34363 _string_39_compare->:  # (payload array byte)
34364     0x11/imm32/alloc-id:fake:payload
34365     # "39/compare->"
34366     0xc/imm32/size
34367     0x33/3 0x39/9 0x2f/slash 0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e 0x2d/dash 0x3e/>
34368 _string_3b_compare<-:  # (payload array byte)
34369     0x11/imm32/alloc-id:fake:payload
34370     # "3b/compare<-"
34371     0xc/imm32/size
34372     0x33/3 0x62/b 0x2f/slash 0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e 0x3c/< 0x2d/dash
34373 _string_3d_compare_eax_with:  # (payload array byte)
34374     0x11/imm32/alloc-id:fake:payload
34375     # "3d/compare-eax-with"
34376     0x13/imm32/size
34377     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
34378 _string_40_increment_eax:  # (payload array byte)
34379     0x11/imm32/alloc-id:fake:payload
34380     # "40/increment-eax"
34381     0x10/imm32/size
34382     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
34383 _string_41_increment_ecx:  # (payload array byte)
34384     0x11/imm32/alloc-id:fake:payload
34385     # "41/increment-ecx"
34386     0x10/imm32/size
34387     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
34388 _string_42_increment_edx:  # (payload array byte)
34389     0x11/imm32/alloc-id:fake:payload
34390     # "42/increment-edx"
34391     0x10/imm32/size
34392     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
34393 _string_43_increment_ebx:  # (payload array byte)
34394     0x11/imm32/alloc-id:fake:payload
34395     # "43/increment-ebx"
34396     0x10/imm32/size
34397     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
34398 _string_46_increment_esi:  # (payload array byte)
34399     0x11/imm32/alloc-id:fake:payload
34400     # "46/increment-esi"
34401     0x10/imm32/size
34402     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
34403 _string_47_increment_edi:  # (payload array byte)
34404     0x11/imm32/alloc-id:fake:payload
34405     # "47/increment-edi"
34406     0x10/imm32/size
34407     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
34408 _string_48_decrement_eax:  # (payload array byte)
34409     0x11/imm32/alloc-id:fake:payload
34410     # "48/decrement-eax"
34411     0x10/imm32/size
34412     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
34413 _string_49_decrement_ecx:  # (payload array byte)
34414     0x11/imm32/alloc-id:fake:payload
34415     # "49/decrement-ecx"
34416     0x10/imm32/size
34417     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
34418 _string_4a_decrement_edx:  # (payload array byte)
34419     0x11/imm32/alloc-id:fake:payload
34420     # "4a/decrement-edx"
34421     0x10/imm32/size
34422     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
34423 _string_4b_decrement_ebx:  # (payload array byte)
34424     0x11/imm32/alloc-id:fake:payload
34425     # "4b/decrement-ebx"
34426     0x10/imm32/size
34427     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
34428 _string_4e_decrement_esi:  # (payload array byte)
34429     0x11/imm32/alloc-id:fake:payload
34430     # "4e/decrement-esi"
34431     0x10/imm32/size
34432     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
34433 _string_4f_decrement_edi:  # (payload array byte)
34434     0x11/imm32/alloc-id:fake:payload
34435     # "4f/decrement-edi"
34436     0x10/imm32/size
34437     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
34438 _string_81_subop_add:  # (payload array byte)
34439     0x11/imm32/alloc-id:fake:payload
34440     # "81 0/subop/add"
34441     0xe/imm32/size
34442     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
34443 _string_81_subop_or:  # (payload array byte)
34444     0x11/imm32/alloc-id:fake:payload
34445     # "81 1/subop/or"
34446     0xd/imm32/size
34447     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
34448 _string_81_subop_and:  # (payload array byte)
34449     0x11/imm32/alloc-id:fake:payload
34450     # "81 4/subop/and"
34451     0xe/imm32/size
34452     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
34453 _string_81_subop_subtract:  # (payload array byte)
34454     0x11/imm32/alloc-id:fake:payload
34455     # "81 5/subop/subtract"
34456     0x13/imm32/size
34457     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
34458 _string_81_subop_xor:  # (payload array byte)
34459     0x11/imm32/alloc-id:fake:payload
34460     # "81 6/subop/xor"
34461     0xe/imm32/size
34462     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
34463 _string_81_subop_compare:  # (payload array byte)
34464     0x11/imm32/alloc-id:fake:payload
34465     # "81 7/subop/compare"
34466     0x12/imm32/size
34467     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
34468 _string_89_<-:  # (payload array byte)
34469     0x11/imm32/alloc-id:fake:payload
34470     # "89/<-"
34471     0x5/imm32/size
34472     0x38/8 0x39/9 0x2f/slash 0x3c/< 0x2d/dash
34473 _string_8b_->:  # (payload array byte)
34474     0x11/imm32/alloc-id:fake:payload
34475     # "8b/->"
34476     0x5/imm32/size
34477     0x38/8 0x62/b 0x2f/slash 0x2d/dash 0x3e/>
34478 _string_8a_copy_byte:
34479     0x11/imm32/alloc-id:fake:payload
34480     # "8a/byte->"
34481     0x9/imm32/size
34482     0x38/8 0x61/a 0x2f// 0x62/b 0x79/y 0x74/t 0x65/e 0x2d/- 0x3e/>
34483 _string_88_copy_byte:
34484     0x11/imm32/alloc-id:fake:payload
34485     # "88/byte<-"
34486     0x9/imm32/size
34487     0x38/8 0x38/8 0x2f// 0x62/b 0x79/y 0x74/t 0x65/e 0x3c/< 0x2d/-
34488 _string_8d_copy_address:  # (payload array byte)
34489     0x11/imm32/alloc-id:fake:payload
34490     # "8d/copy-address"
34491     0xf/imm32/size
34492     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
34493 _string_b8_copy_to_eax:  # (payload array byte)
34494     0x11/imm32/alloc-id:fake:payload
34495     # "b8/copy-to-eax"
34496     0xe/imm32/size
34497     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
34498 _string_b9_copy_to_ecx:  # (payload array byte)
34499     0x11/imm32/alloc-id:fake:payload
34500     # "b9/copy-to-ecx"
34501     0xe/imm32/size
34502     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
34503 _string_ba_copy_to_edx:  # (payload array byte)
34504     0x11/imm32/alloc-id:fake:payload
34505     # "ba/copy-to-edx"
34506     0xe/imm32/size
34507     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
34508 _string_bb_copy_to_ebx:  # (payload array byte)
34509     0x11/imm32/alloc-id:fake:payload
34510     # "bb/copy-to-ebx"
34511     0xe/imm32/size
34512     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
34513 _string_be_copy_to_esi:  # (payload array byte)
34514     0x11/imm32/alloc-id:fake:payload
34515     # "be/copy-to-esi"
34516     0xe/imm32/size
34517     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
34518 _string_bf_copy_to_edi:  # (payload array byte)
34519     0x11/imm32/alloc-id:fake:payload
34520     # "bf/copy-to-edi"
34521     0xe/imm32/size
34522     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
34523 _string_c7_subop_copy:  # (payload array byte)
34524     0x11/imm32/alloc-id:fake:payload
34525     # "c7 0/subop/copy"
34526     0xf/imm32/size
34527     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
34528 _string_e9_jump_label:  # (payload array byte)
34529     0x11/imm32/alloc-id:fake:payload
34530     # "e9/jump"
34531     0x7/imm32/size
34532     0x65/e 0x39/9 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p
34533 _string_e9_jump_break:  # (payload array byte)
34534     0x11/imm32/alloc-id:fake:payload
34535     # "e9/jump break/disp32"
34536     0x14/imm32/size
34537     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
34538 _string_e9_jump_loop:  # (payload array byte)
34539     0x11/imm32/alloc-id:fake:payload
34540     # "e9/jump loop/disp32"
34541     0x13/imm32/size
34542     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
34543 _string_f7_subop_negate:
34544     0x11/imm32/alloc-id:fake:payload
34545     # "f7 3/subop/negate"
34546     0x11/imm32/size
34547     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
34548 _string_ff_subop_increment:  # (payload array byte)
34549     0x11/imm32/alloc-id:fake:payload
34550     # "ff 0/subop/increment"
34551     0x14/imm32/size
34552     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
34553 _string_ff_subop_decrement:  # (payload array byte)
34554     0x11/imm32/alloc-id:fake:payload
34555     # "ff 1/subop/decrement"
34556     0x14/imm32/size
34557     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
34558 _string_c1_subop_shift_left:  # (payload array byte)
34559     0x11/imm32/alloc-id:fake:payload
34560     # "c1/shift 4/subop/left"
34561     0x15/imm32/size
34562     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
34563 _string_c1_subop_shift_right_padding_zeroes:  # (payload array byte)
34564     0x11/imm32/alloc-id:fake:payload
34565     # "c1/shift 5/subop/right-padding-zeroes"
34566     0x25/imm32/size
34567     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
34568 _string_c1_subop_shift_right_preserving_sign:  # (payload array byte)
34569     0x11/imm32/alloc-id:fake:payload
34570     # "c1/shift 7/subop/right-preserving-sign"
34571     0x26/imm32/size
34572     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
34573 
34574 Single-int-var-in-mem:  # (payload list var)
34575     0x11/imm32/alloc-id:fake:payload
34576     0x11/imm32/alloc-id:fake
34577     Int-var-in-mem/imm32
34578     0/imm32/next
34579     0/imm32/next
34580 
34581 Int-var-in-mem:  # (payload var)
34582     0x11/imm32/alloc-id:fake:payload
34583     0/imm32/name
34584     0/imm32/name
34585     0x11/imm32/alloc-id:fake
34586     Type-int/imm32
34587     1/imm32/some-block-depth
34588     1/imm32/some-stack-offset
34589     0/imm32/no-register
34590     0/imm32/no-register
34591 
34592 # Not really legal, but closest we can currently represent a dereference of an (addr byte)
34593 Single-byte-var-in-mem:  # (payload list var)
34594     0x11/imm32/alloc-id:fake:payload
34595     0x11/imm32/alloc-id:fake
34596     Byte-var-in-mem/imm32
34597     0/imm32/next
34598     0/imm32/next
34599 
34600 # Not really legal, but closest we can currently represent a dereference of an (addr byte)
34601 Byte-var-in-mem:  # (payload var)
34602     0x11/imm32/alloc-id:fake:payload
34603     0/imm32/name
34604     0/imm32/name
34605     0x11/imm32/alloc-id:fake
34606     Type-byte/imm32
34607     1/imm32/some-block-depth
34608     1/imm32/some-stack-offset
34609     0/imm32/no-register
34610     0/imm32/no-register
34611 
34612 Two-args-int-stack-int-reg:  # (payload list var)
34613     0x11/imm32/alloc-id:fake:payload
34614     0x11/imm32/alloc-id:fake
34615     Int-var-in-mem/imm32
34616     0x11/imm32/alloc-id:fake
34617     Single-int-var-in-some-register/imm32/next
34618 
34619 Two-int-args-in-regs:  # (payload list var)
34620     0x11/imm32/alloc-id:fake:payload
34621     0x11/imm32/alloc-id:fake
34622     Int-var-in-some-register/imm32
34623     0x11/imm32/alloc-id:fake
34624     Single-int-var-in-some-register/imm32/next
34625 
34626 # Not really legal, but closest we can currently represent a dereference of an (addr byte)
34627 Two-args-byte-stack-byte-reg:  # (payload list var)
34628     0x11/imm32/alloc-id:fake:payload
34629     0x11/imm32/alloc-id:fake
34630     Byte-var-in-mem/imm32
34631     0x11/imm32/alloc-id:fake
34632     Single-byte-var-in-some-register/imm32/next
34633 
34634 Two-args-int-reg-int-stack:  # (payload list var)
34635     0x11/imm32/alloc-id:fake:payload
34636     0x11/imm32/alloc-id:fake
34637     Int-var-in-some-register/imm32
34638     0x11/imm32/alloc-id:fake
34639     Single-int-var-in-mem/imm32/next
34640 
34641 Two-args-int-eax-int-literal:  # (payload list var)
34642     0x11/imm32/alloc-id:fake:payload
34643     0x11/imm32/alloc-id:fake
34644     Int-var-in-eax/imm32
34645     0x11/imm32/alloc-id:fake
34646     Single-lit-var/imm32/next
34647 
34648 Int-var-and-literal:  # (payload list var)
34649     0x11/imm32/alloc-id:fake:payload
34650     0x11/imm32/alloc-id:fake
34651     Int-var-in-mem/imm32
34652     0x11/imm32/alloc-id:fake
34653     Single-lit-var/imm32/next
34654 
34655 Int-var-in-register-and-literal:  # (payload list var)
34656     0x11/imm32/alloc-id:fake:payload
34657     0x11/imm32/alloc-id:fake
34658     Int-var-in-some-register/imm32
34659     0x11/imm32/alloc-id:fake
34660     Single-lit-var/imm32/next
34661 
34662 Two-float-args-in-regs:  # (payload list var)
34663     0x11/imm32/alloc-id:fake:payload
34664     0x11/imm32/alloc-id:fake
34665     Float-var-in-some-register/imm32
34666     0x11/imm32/alloc-id:fake
34667     Single-float-var-in-some-register/imm32/next
34668 
34669 Two-args-float-reg-float-stack:  # (payload list var)
34670     0x11/imm32/alloc-id:fake:payload
34671     0x11/imm32/alloc-id:fake
34672     Float-var-in-some-register/imm32
34673     0x11/imm32/alloc-id:fake
34674     Single-float-var-in-mem/imm32/next
34675 
34676 Two-args-float-stack-float-reg:  # (payload list var)
34677     0x11/imm32/alloc-id:fake:payload
34678     0x11/imm32/alloc-id:fake
34679     Float-var-in-mem/imm32
34680     0x11/imm32/alloc-id:fake
34681     Single-float-var-in-some-register/imm32/next
34682 
34683 Single-int-var-in-some-register:  # (payload list var)
34684     0x11/imm32/alloc-id:fake:payload
34685     0x11/imm32/alloc-id:fake
34686     Int-var-in-some-register/imm32
34687     0/imm32/next
34688     0/imm32/next
34689 
34690 Single-addr-var-in-some-register:  # (payload list var)
34691     0x11/imm32/alloc-id:fake:payload
34692     0x11/imm32/alloc-id:fake
34693     Addr-var-in-some-register/imm32
34694     0/imm32/next
34695     0/imm32/next
34696 
34697 Single-byte-var-in-some-register:  # (payload list var)
34698     0x11/imm32/alloc-id:fake:payload
34699     0x11/imm32/alloc-id:fake
34700     Byte-var-in-some-register/imm32
34701     0/imm32/next
34702     0/imm32/next
34703 
34704 Int-var-in-some-register:  # (payload var)
34705     0x11/imm32/alloc-id:fake:payload
34706     0/imm32/name
34707     0/imm32/name
34708     0x11/imm32/alloc-id:fake
34709     Type-int/imm32
34710     1/imm32/some-block-depth
34711     0/imm32/no-stack-offset
34712     0x11/imm32/alloc-id:fake
34713     Any-register/imm32
34714 
34715 Any-register:  # (payload array byte)
34716     0x11/imm32/alloc-id:fake:payload
34717     1/imm32/size
34718     # data
34719     2a/asterisk
34720 
34721 Addr-var-in-some-register:  # (payload var)
34722     0x11/imm32/alloc-id:fake:payload
34723     0/imm32/name
34724     0/imm32/name
34725     0x11/imm32/alloc-id:fake
34726     Type-addr/imm32
34727     1/imm32/some-block-depth
34728     0/imm32/no-stack-offset
34729     0x11/imm32/alloc-id:fake
34730     Any-register/imm32
34731 
34732 Byte-var-in-some-register:  # (payload var)
34733     0x11/imm32/alloc-id:fake:payload
34734     0/imm32/name
34735     0/imm32/name
34736     0x11/imm32/alloc-id:fake
34737     Type-byte/imm32
34738     1/imm32/some-block-depth
34739     0/imm32/no-stack-offset
34740     0x11/imm32/alloc-id:fake
34741     Any-register/imm32
34742 
34743 Single-int-var-in-eax:  # (payload list var)
34744     0x11/imm32/alloc-id:fake:payload
34745     0x11/imm32/alloc-id:fake
34746     Int-var-in-eax/imm32
34747     0/imm32/next
34748     0/imm32/next
34749 
34750 Int-var-in-eax:
34751     0x11/imm32/alloc-id:fake:payload
34752     0/imm32/name
34753     0/imm32/name
34754     0x11/imm32/alloc-id:fake
34755     Type-int/imm32
34756     1/imm32/some-block-depth
34757     0/imm32/no-stack-offset
34758     0x11/imm32/alloc-id:fake
34759     $Mu-register-eax/imm32  # can't use Register-eax only to keep our buggy tools/treeshake.cc happy (TODO)
34760 
34761 Single-int-var-in-ecx:  # (payload list var)
34762     0x11/imm32/alloc-id:fake:payload
34763     0x11/imm32/alloc-id:fake
34764     Int-var-in-ecx/imm32
34765     0/imm32/next
34766     0/imm32/next
34767 
34768 Int-var-in-ecx:
34769     0x11/imm32/alloc-id:fake:payload
34770     0/imm32/name
34771     0/imm32/name
34772     0x11/imm32/alloc-id:fake
34773     Type-int/imm32
34774     1/imm32/some-block-depth
34775     0/imm32/no-stack-offset
34776     0x11/imm32/alloc-id:fake
34777     $Register-ecx/imm32/register
34778 
34779 Single-int-var-in-edx:  # (payload list var)
34780     0x11/imm32/alloc-id:fake:payload
34781     0x11/imm32/alloc-id:fake
34782     Int-var-in-edx/imm32
34783     0/imm32/next
34784     0/imm32/next
34785 
34786 Int-var-in-edx:  # (payload list var)
34787     0x11/imm32/alloc-id:fake:payload
34788     0/imm32/name
34789     0/imm32/name
34790     0x11/imm32/alloc-id:fake
34791     Type-int/imm32
34792     1/imm32/some-block-depth
34793     0/imm32/no-stack-offset
34794     0x11/imm32/alloc-id:fake
34795     $Register-edx/imm32/register
34796 
34797 Single-int-var-in-ebx:  # (payload list var)
34798     0x11/imm32/alloc-id:fake:payload
34799     0x11/imm32/alloc-id:fake
34800     Int-var-in-ebx/imm32
34801     0/imm32/next
34802     0/imm32/next
34803 
34804 Int-var-in-ebx:  # (payload list var)
34805     0x11/imm32/alloc-id:fake:payload
34806     0/imm32/name
34807     0/imm32/name
34808     0x11/imm32/alloc-id:fake
34809     Type-int/imm32
34810     1/imm32/some-block-depth
34811     0/imm32/no-stack-offset
34812     0x11/imm32/alloc-id:fake
34813     $Register-ebx/imm32/register
34814 
34815 Single-int-var-in-esi:  # (payload list var)
34816     0x11/imm32/alloc-id:fake:payload
34817     0x11/imm32/alloc-id:fake
34818     Int-var-in-esi/imm32
34819     0/imm32/next
34820     0/imm32/next
34821 
34822 Int-var-in-esi:  # (payload list var)
34823     0x11/imm32/alloc-id:fake:payload
34824     0/imm32/name
34825     0/imm32/name
34826     0x11/imm32/alloc-id:fake
34827     Type-int/imm32
34828     1/imm32/some-block-depth
34829     0/imm32/no-stack-offset
34830     0x11/imm32/alloc-id:fake
34831     $Register-esi/imm32/register
34832 
34833 Single-int-var-in-edi:  # (payload list var)
34834     0x11/imm32/alloc-id:fake:payload
34835     0x11/imm32/alloc-id:fake
34836     Int-var-in-edi/imm32
34837     0/imm32/next
34838     0/imm32/next
34839 
34840 Int-var-in-edi:  # (payload list var)
34841     0x11/imm32/alloc-id:fake:payload
34842     0/imm32/name
34843     0/imm32/name
34844     0x11/imm32/alloc-id:fake
34845     Type-int/imm32
34846     1/imm32/some-block-depth
34847     0/imm32/no-stack-offset
34848     0x11/imm32/alloc-id:fake
34849     $Register-edi/imm32/register
34850 
34851 Single-lit-var:  # (payload list var)
34852     0x11/imm32/alloc-id:fake:payload
34853     0x11/imm32/alloc-id:fake
34854     Lit-var/imm32
34855     0/imm32/next
34856     0/imm32/next
34857 
34858 Lit-var:  # (payload var)
34859     0x11/imm32/alloc-id:fake:payload
34860     0/imm32/name
34861     0/imm32/name
34862     0x11/imm32/alloc-id:fake
34863     Type-literal/imm32
34864     1/imm32/some-block-depth
34865     0/imm32/no-stack-offset
34866     0/imm32/no-register
34867     0/imm32/no-register
34868 
34869 Single-float-var-in-mem:  # (payload list var)
34870     0x11/imm32/alloc-id:fake:payload
34871     0x11/imm32/alloc-id:fake
34872     Float-var-in-mem/imm32
34873     0/imm32/next
34874     0/imm32/next
34875 
34876 Float-var-in-mem:  # (payload var)
34877     0x11/imm32/alloc-id:fake:payload
34878     0/imm32/name
34879     0/imm32/name
34880     0x11/imm32/alloc-id:fake
34881     Type-float/imm32
34882     1/imm32/some-block-depth
34883     1/imm32/some-stack-offset
34884     0/imm32/no-register
34885     0/imm32/no-register
34886 
34887 Single-float-var-in-some-register:  # (payload list var)
34888     0x11/imm32/alloc-id:fake:payload
34889     0x11/imm32/alloc-id:fake
34890     Float-var-in-some-register/imm32
34891     0/imm32/next
34892     0/imm32/next
34893 
34894 Float-var-in-some-register:  # (payload var)
34895     0x11/imm32/alloc-id:fake:payload
34896     0/imm32/name
34897     0/imm32/name
34898     0x11/imm32/alloc-id:fake
34899     Type-float/imm32
34900     1/imm32/some-block-depth
34901     0/imm32/no-stack-offset
34902     0x11/imm32/alloc-id:fake
34903     Any-register/imm32
34904 
34905 Type-int:  # (payload type-tree)
34906     0x11/imm32/alloc-id:fake:payload
34907     1/imm32/is-atom
34908     1/imm32/value:int
34909     0/imm32/left:unused
34910     0/imm32/right:null
34911     0/imm32/right:null
34912 
34913 Type-literal:  # (payload type-tree)
34914     0x11/imm32/alloc-id:fake:payload
34915     1/imm32/is-atom
34916     0/imm32/value:literal
34917     0/imm32/left:unused
34918     0/imm32/right:null
34919     0/imm32/right:null
34920 
34921 Type-addr:  # (payload type-tree)
34922     0x11/imm32/alloc-id:fake:payload
34923     1/imm32/is-atom
34924     2/imm32/value:addr
34925     0/imm32/left:unused
34926     0/imm32/right:null
34927     0/imm32/right:null
34928 
34929 Type-byte:  # (payload type-tree)
34930     0x11/imm32/alloc-id:fake:payload
34931     1/imm32/is-atom
34932     8/imm32/value:byte
34933     0/imm32/left:unused
34934     0/imm32/right:null
34935     0/imm32/right:null
34936 
34937 Type-float:  # (payload type-tree)
34938     0x11/imm32/alloc-id:fake:payload
34939     1/imm32/is-atom
34940     0xf/imm32/value:float
34941     0/imm32/left:unused
34942     0/imm32/right:null
34943     0/imm32/right:null
34944 
34945 == code
34946 emit-subx-primitive:  # out: (addr buffered-file), stmt: (addr stmt), primitive: (addr primitive), err: (addr buffered-file), ed: (addr exit-descriptor)
34947     # . prologue
34948     55/push-ebp
34949     89/<- %ebp 4/r32/esp
34950     # . save registers
34951     50/push-eax
34952     51/push-ecx
34953     # ecx = primitive
34954     8b/-> *(ebp+0x10) 1/r32/ecx
34955     # emit primitive name
34956     (emit-indent *(ebp+8) *Curr-block-depth)
34957     (lookup *(ecx+0x18) *(ecx+0x1c))  # Primitive-subx-name Primitive-subx-name => eax
34958     (write-buffered *(ebp+8) %eax)
34959     # emit rm32 if necessary
34960     (emit-subx-rm32 *(ebp+8) *(ecx+0x20) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # Primitive-subx-rm32
34961     # emit xm32 if necessary
34962     (emit-subx-rm32 *(ebp+8) *(ecx+0x34) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # Primitive-subx-xm32
34963     # emit r32 if necessary
34964     (emit-subx-r32 *(ebp+8) *(ecx+0x24) *(ebp+0xc))  # Primitive-subx-r32
34965     # emit x32 if necessary
34966     (emit-subx-x32 *(ebp+8) *(ecx+0x38) *(ebp+0xc))  # Primitive-subx-x32
34967     # emit imm32 if necessary
34968     (emit-subx-imm32 *(ebp+8) *(ecx+0x28) *(ebp+0xc))  # Primitive-subx-imm32
34969     # emit imm8 if necessary
34970     (emit-subx-imm8 *(ebp+8) *(ecx+0x2c) *(ebp+0xc))  # Primitive-subx-imm8
34971     # emit disp32 if necessary
34972     (emit-subx-disp32 *(ebp+8) *(ecx+0x30) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # Primitive-subx-disp32
34973     (write-buffered *(ebp+8) Newline)
34974 $emit-subx-primitive:end:
34975     # . restore registers
34976     59/pop-to-ecx
34977     58/pop-to-eax
34978     # . epilogue
34979     89/<- %esp 5/r32/ebp
34980     5d/pop-to-ebp
34981     c3/return
34982 
34983 emit-subx-rm32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
34984     # . prologue
34985     55/push-ebp
34986     89/<- %ebp 4/r32/esp
34987     # . save registers
34988     50/push-eax
34989     # if (l == 0) return
34990     81 7/subop/compare *(ebp+0xc) 0/imm32
34991     74/jump-if-= $emit-subx-rm32:end/disp8
34992     # var v/eax: (addr stmt-var)
34993     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # => eax
34994     (emit-subx-var-as-rm32 *(ebp+8) %eax)
34995 $emit-subx-rm32:end:
34996     # . restore registers
34997     58/pop-to-eax
34998     # . epilogue
34999     89/<- %esp 5/r32/ebp
35000     5d/pop-to-ebp
35001     c3/return
35002 
35003 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)
35004     # . prologue
35005     55/push-ebp
35006     89/<- %ebp 4/r32/esp
35007     # . save registers
35008     51/push-ecx
35009     # eax = l
35010     8b/-> *(ebp+0xc) 0/r32/eax
35011     # ecx = stmt
35012     8b/-> *(ebp+8) 1/r32/ecx
35013     # if (l == 1) return stmt->inouts
35014     {
35015       3d/compare-eax-and 1/imm32
35016       75/jump-if-!= break/disp8
35017 $get-stmt-operand-from-arg-location:1:
35018       (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
35019       eb/jump $get-stmt-operand-from-arg-location:end/disp8
35020     }
35021     # if (l == 2) return stmt->inouts->next
35022     {
35023       3d/compare-eax-and 2/imm32
35024       75/jump-if-!= break/disp8
35025 $get-stmt-operand-from-arg-location:2:
35026       (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
35027       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
35028       eb/jump $get-stmt-operand-from-arg-location:end/disp8
35029     }
35030     # if (l == 3) return stmt->outputs
35031     {
35032       3d/compare-eax-and 3/imm32
35033       75/jump-if-!= break/disp8
35034 $get-stmt-operand-from-arg-location:3:
35035       (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
35036       eb/jump $get-stmt-operand-from-arg-location:end/disp8
35037     }
35038     # abort
35039     e9/jump $get-stmt-operand-from-arg-location:abort/disp32
35040 $get-stmt-operand-from-arg-location:end:
35041     # . restore registers
35042     59/pop-to-ecx
35043     # . epilogue
35044     89/<- %esp 5/r32/ebp
35045     5d/pop-to-ebp
35046     c3/return
35047 
35048 $get-stmt-operand-from-arg-location:abort:
35049     # error("invalid arg-location " eax)
35050     (write-buffered *(ebp+0x10) "invalid arg-location ")
35051     (write-int32-hex-buffered *(ebp+0x10) %eax)
35052     (write-buffered *(ebp+0x10) Newline)
35053     (flush *(ebp+0x10))
35054     (stop *(ebp+0x14) 1)
35055     # never gets here
35056 
35057 emit-subx-r32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
35058     # . prologue
35059     55/push-ebp
35060     89/<- %ebp 4/r32/esp
35061     # . save registers
35062     50/push-eax
35063     51/push-ecx
35064     # if (l == 0) return
35065     81 7/subop/compare *(ebp+0xc) 0/imm32
35066     0f 84/jump-if-= $emit-subx-r32:end/disp32
35067     # var v/eax: (addr stmt-var)
35068     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
35069     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
35070     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
35071 #?     (write-buffered Stderr "looking up ")
35072 #?     (write-buffered Stderr %eax)
35073 #?     (write-buffered Stderr Newline)
35074 #?     (flush Stderr)
35075     (maybe-get Mu-registers %eax 0xc)  # => eax: (addr register-index)
35076     (write-buffered *(ebp+8) Space)
35077     (write-int32-hex-buffered *(ebp+8) *eax)
35078     (write-buffered *(ebp+8) "/r32")
35079 $emit-subx-r32:end:
35080     # . restore registers
35081     59/pop-to-ecx
35082     58/pop-to-eax
35083     # . epilogue
35084     89/<- %esp 5/r32/ebp
35085     5d/pop-to-ebp
35086     c3/return
35087 
35088 emit-subx-x32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
35089     # . prologue
35090     55/push-ebp
35091     89/<- %ebp 4/r32/esp
35092     # . save registers
35093     50/push-eax
35094     51/push-ecx
35095     # if (l == 0) return
35096     81 7/subop/compare *(ebp+0xc) 0/imm32
35097     0f 84/jump-if-= $emit-subx-x32:end/disp32
35098     # var v/eax: (addr stmt-var)
35099     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
35100     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
35101     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
35102 #?     (write-buffered Stderr "looking up ")
35103 #?     (write-buffered Stderr %eax)
35104 #?     (write-buffered Stderr Newline)
35105 #?     (flush Stderr)
35106     (maybe-get Mu-registers %eax 0xc)  # => eax: (addr register-index)
35107     (write-buffered *(ebp+8) Space)
35108     (write-int32-hex-buffered *(ebp+8) *eax)
35109     (write-buffered *(ebp+8) "/x32")
35110 $emit-subx-x32:end:
35111     # . restore registers
35112     59/pop-to-ecx
35113     58/pop-to-eax
35114     # . epilogue
35115     89/<- %esp 5/r32/ebp
35116     5d/pop-to-ebp
35117     c3/return
35118 
35119 emit-subx-imm32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
35120     # . prologue
35121     55/push-ebp
35122     89/<- %ebp 4/r32/esp
35123     # . save registers
35124     50/push-eax
35125     51/push-ecx
35126     # if (l == 0) return
35127     81 7/subop/compare *(ebp+0xc) 0/imm32
35128     0f 84/jump-if-= $emit-subx-imm32:end/disp32
35129     # var v/eax: (handle var)
35130     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
35131     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
35132     (lookup *eax *(eax+4))  # Var-name Var-name => eax
35133     (write-buffered *(ebp+8) Space)
35134     (write-buffered *(ebp+8) %eax)
35135     (write-buffered *(ebp+8) "/imm32")
35136 $emit-subx-imm32:end:
35137     # . restore registers
35138     59/pop-to-ecx
35139     58/pop-to-eax
35140     # . epilogue
35141     89/<- %esp 5/r32/ebp
35142     5d/pop-to-ebp
35143     c3/return
35144 
35145 emit-subx-imm8:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
35146     # . prologue
35147     55/push-ebp
35148     89/<- %ebp 4/r32/esp
35149     # . save registers
35150     50/push-eax
35151     51/push-ecx
35152     # if (l == 0) return
35153     81 7/subop/compare *(ebp+0xc) 0/imm32
35154     0f 84/jump-if-= $emit-subx-imm32:end/disp32
35155     # var v/eax: (handle var)
35156     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
35157     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
35158     (lookup *eax *(eax+4))  # Var-name Var-name => eax
35159     (write-buffered *(ebp+8) Space)
35160     (write-buffered *(ebp+8) %eax)
35161     (write-buffered *(ebp+8) "/imm8")
35162 $emit-subx-imm8:end:
35163     # . restore registers
35164     59/pop-to-ecx
35165     58/pop-to-eax
35166     # . epilogue
35167     89/<- %esp 5/r32/ebp
35168     5d/pop-to-ebp
35169     c3/return
35170 
35171 emit-subx-disp32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
35172     # . prologue
35173     55/push-ebp
35174     89/<- %ebp 4/r32/esp
35175     # . save registers
35176     50/push-eax
35177     51/push-ecx
35178     # if (location == 0) return
35179     81 7/subop/compare *(ebp+0xc) 0/imm32
35180     0f 84/jump-if-= $emit-subx-disp32:end/disp32
35181     # var v/eax: (addr stmt-var)
35182     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # => eax
35183     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
35184     (lookup *eax *(eax+4))  # Var-name Var-name => eax
35185     (write-buffered *(ebp+8) Space)
35186     (write-buffered *(ebp+8) %eax)
35187     # hack: if instruction operation starts with "break", emit ":break"
35188     # var name/ecx: (addr array byte) = lookup(stmt->operation)
35189     8b/-> *(ebp+0x10) 0/r32/eax
35190     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
35191     89/<- %ecx 0/r32/eax
35192     {
35193       (string-starts-with? %ecx "break")  # => eax
35194       3d/compare-eax-and 0/imm32/false
35195       74/jump-if-= break/disp8
35196       (write-buffered *(ebp+8) ":break")
35197     }
35198     # hack: if instruction operation starts with "loop", emit ":loop"
35199     {
35200       (string-starts-with? %ecx "loop")  # => eax
35201       3d/compare-eax-and 0/imm32/false
35202       74/jump-if-= break/disp8
35203       (write-buffered *(ebp+8) ":loop")
35204     }
35205     (write-buffered *(ebp+8) "/disp32")
35206 $emit-subx-disp32:end:
35207     # . restore registers
35208     59/pop-to-ecx
35209     58/pop-to-eax
35210     # . epilogue
35211     89/<- %esp 5/r32/ebp
35212     5d/pop-to-ebp
35213     c3/return
35214 
35215 emit-call:  # out: (addr buffered-file), stmt: (addr stmt)
35216     # . prologue
35217     55/push-ebp
35218     89/<- %ebp 4/r32/esp
35219     # . save registers
35220     50/push-eax
35221     51/push-ecx
35222     #
35223     (emit-indent *(ebp+8) *Curr-block-depth)
35224     (write-buffered *(ebp+8) "(")
35225     # ecx = stmt
35226     8b/-> *(ebp+0xc) 1/r32/ecx
35227     # - emit function name
35228     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
35229     (write-buffered *(ebp+8) %eax)
35230     # - emit arguments
35231     # var curr/eax: (addr stmt-var) = lookup(stmt->inouts)
35232     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
35233     {
35234       # if (curr == null) break
35235       3d/compare-eax-and 0/imm32
35236       74/jump-if-= break/disp8
35237       #
35238       (emit-subx-call-operand *(ebp+8) %eax)
35239       # curr = lookup(curr->next)
35240       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
35241       eb/jump loop/disp8
35242     }
35243     #
35244     (write-buffered *(ebp+8) ")\n")
35245 $emit-call:end:
35246     # . restore registers
35247     59/pop-to-ecx
35248     58/pop-to-eax
35249     # . epilogue
35250     89/<- %esp 5/r32/ebp
35251     5d/pop-to-ebp
35252     c3/return
35253 
35254 emit-subx-call-operand:  # out: (addr buffered-file), s: (addr stmt-var)
35255     # shares code with emit-subx-var-as-rm32
35256     # . prologue
35257     55/push-ebp
35258     89/<- %ebp 4/r32/esp
35259     # . save registers
35260     50/push-eax
35261     51/push-ecx
35262     56/push-esi
35263     # ecx = s
35264     8b/-> *(ebp+0xc) 1/r32/ecx
35265     # var operand/esi: (addr var) = lookup(s->value)
35266     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
35267     89/<- %esi 0/r32/eax
35268     # if (operand->register && !s->is-deref?) emit "%__"
35269     {
35270 $emit-subx-call-operand:check-for-register-direct:
35271       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
35272       74/jump-if-= break/disp8
35273       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
35274       75/jump-if-!= break/disp8
35275 $emit-subx-call-operand:register-direct:
35276       (write-buffered *(ebp+8) " %")
35277       (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
35278       (write-buffered *(ebp+8) %eax)
35279       e9/jump $emit-subx-call-operand:end/disp32
35280     }
35281     # else if (operand->register && s->is-deref?) emit "*__"
35282     {
35283 $emit-subx-call-operand:check-for-register-indirect:
35284       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
35285       74/jump-if-= break/disp8
35286       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
35287       74/jump-if-= break/disp8
35288 $emit-subx-call-operand:register-indirect:
35289       (emit-subx-call-operand-register-indirect *(ebp+8) %esi)
35290       e9/jump $emit-subx-call-operand:end/disp32
35291     }
35292     # else if (operand->stack-offset) emit "*(ebp+__)"
35293     {
35294       81 7/subop/compare *(esi+0x14) 0/imm32  # Var-offset
35295       74/jump-if-= break/disp8
35296 $emit-subx-call-operand:stack:
35297       (emit-subx-call-operand-stack *(ebp+8) %esi)
35298       e9/jump $emit-subx-call-operand:end/disp32
35299     }
35300     # else if (operand->type == literal) emit "__"
35301     {
35302       (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
35303       81 7/subop/compare *(eax+4) 0/imm32  # Type-tree-value
35304       75/jump-if-!= break/disp8
35305 $emit-subx-call-operand:literal:
35306       (write-buffered *(ebp+8) Space)
35307       (lookup *esi *(esi+4))  # Var-name Var-name => eax
35308       (write-buffered *(ebp+8) %eax)
35309       e9/jump $emit-subx-call-operand:end/disp32
35310     }
35311     # else if (operand->type == literal-string) emit "__"
35312     {
35313       (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
35314       81 7/subop/compare *(eax+4) 0x10/imm32  # Type-tree-value
35315       75/jump-if-!= break/disp8
35316 $emit-subx-call-operand:literal-string:
35317       (write-buffered *(ebp+8) Space)
35318       (lookup *esi *(esi+4))  # Var-name Var-name => eax
35319       (write-buffered *(ebp+8) %eax)
35320     }
35321 $emit-subx-call-operand:end:
35322     # . restore registers
35323     5e/pop-to-esi
35324     59/pop-to-ecx
35325     58/pop-to-eax
35326     # . epilogue
35327     89/<- %esp 5/r32/ebp
35328     5d/pop-to-ebp
35329     c3/return
35330 
35331 emit-subx-call-operand-register-indirect:  # out: (addr buffered-file), v: (addr var)
35332     # . prologue
35333     55/push-ebp
35334     89/<- %ebp 4/r32/esp
35335     # . save registers
35336     50/push-eax
35337     51/push-ecx
35338     56/push-esi
35339     # esi = v
35340     8b/-> *(ebp+0xc) 6/r32/esi
35341     # var size/ecx: int = size-of-deref(v)
35342     (size-of-deref %esi)  # => eax
35343     89/<- %ecx 0/r32/eax
35344     # var reg-name/esi: (addr array byte) = lookup(v->register)
35345     (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
35346     89/<- %esi 0/r32/eax
35347     # TODO: assert size is a multiple of 4
35348     # var i/eax: int = 0
35349     b8/copy-to-eax 0/imm32
35350     {
35351 $emit-subx-call-operand-register-indirect:loop:
35352       # if (i >= size) break
35353       39/compare %eax 1/r32/ecx
35354       7d/jump-if->= break/disp8
35355       # emit " *(" v->register "+" i ")"
35356       (write-buffered *(ebp+8) " *(")
35357       (write-buffered *(ebp+8) %esi)
35358       (write-buffered *(ebp+8) "+")
35359       (write-int32-hex-buffered *(ebp+8) %eax)
35360       (write-buffered *(ebp+8) ")")
35361       # i += 4
35362       05/add-to-eax 4/imm32
35363       #
35364       eb/jump loop/disp8
35365     }
35366 $emit-subx-call-operand-register-indirect:end:
35367     # . restore registers
35368     5e/pop-to-esi
35369     59/pop-to-ecx
35370     58/pop-to-eax
35371     # . epilogue
35372     89/<- %esp 5/r32/ebp
35373     5d/pop-to-ebp
35374     c3/return
35375 
35376 emit-subx-call-operand-stack:  # out: (addr buffered-file), v: (addr var)
35377     # . prologue
35378     55/push-ebp
35379     89/<- %ebp 4/r32/esp
35380     # . save registers
35381     50/push-eax
35382     51/push-ecx
35383     56/push-esi
35384     # esi = v
35385     8b/-> *(ebp+0xc) 6/r32/esi
35386     # var curr/ecx: int = v->offset
35387     8b/-> *(esi+0x14) 1/r32/ecx  # Var-offset
35388     # var max/eax: int = v->offset + size-of(v)
35389     (size-of %esi)  # => eax
35390     # TODO: assert size is a multiple of 4
35391     01/add-to %eax 1/r32/ecx
35392     {
35393 $emit-subx-call-operand-stack:loop:
35394       # if (curr >= max) break
35395       39/compare %ecx 0/r32/eax
35396       7d/jump-if->= break/disp8
35397       # emit " *(ebp+" curr ")"
35398       (write-buffered *(ebp+8) " *(ebp+")
35399       (write-int32-hex-buffered *(ebp+8) %ecx)
35400       (write-buffered *(ebp+8) ")")
35401       # i += 4
35402       81 0/subop/add %ecx 4/imm32
35403       #
35404       eb/jump loop/disp8
35405     }
35406 $emit-subx-call-operand-stack:end:
35407     # . restore registers
35408     5e/pop-to-esi
35409     59/pop-to-ecx
35410     58/pop-to-eax
35411     # . epilogue
35412     89/<- %esp 5/r32/ebp
35413     5d/pop-to-ebp
35414     c3/return
35415 
35416 emit-subx-var-as-rm32:  # out: (addr buffered-file), s: (addr stmt-var)
35417     # . prologue
35418     55/push-ebp
35419     89/<- %ebp 4/r32/esp
35420     # . save registers
35421     50/push-eax
35422     51/push-ecx
35423     56/push-esi
35424     # ecx = s
35425     8b/-> *(ebp+0xc) 1/r32/ecx
35426     # var operand/esi: (addr var) = lookup(s->value)
35427     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
35428     89/<- %esi 0/r32/eax
35429     # if (operand->register && s->is-deref?) emit "*__"
35430     {
35431 $emit-subx-var-as-rm32:check-for-register-indirect:
35432       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
35433       74/jump-if-= break/disp8
35434       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
35435       74/jump-if-= break/disp8
35436 $emit-subx-var-as-rm32:register-indirect:
35437       (write-buffered *(ebp+8) " *")
35438       (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
35439       (write-buffered *(ebp+8) %eax)
35440       e9/jump $emit-subx-var-as-rm32:end/disp32
35441     }
35442     # if (operand->register && !s->is-deref?) emit "%__"
35443     {
35444 $emit-subx-var-as-rm32:check-for-register-direct:
35445       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
35446       74/jump-if-= break/disp8
35447       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
35448       75/jump-if-!= break/disp8
35449 $emit-subx-var-as-rm32:register-direct:
35450       (write-buffered *(ebp+8) " %")
35451       (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
35452       (write-buffered *(ebp+8) %eax)
35453       e9/jump $emit-subx-var-as-rm32:end/disp32
35454     }
35455     # else if (operand->stack-offset) emit "*(ebp+__)"
35456     {
35457       81 7/subop/compare *(esi+0x14) 0/imm32  # Var-offset
35458       74/jump-if-= break/disp8
35459 $emit-subx-var-as-rm32:stack:
35460       (write-buffered *(ebp+8) Space)
35461       (write-buffered *(ebp+8) "*(ebp+")
35462       (write-int32-hex-buffered *(ebp+8) *(esi+0x14))  # Var-offset
35463       (write-buffered *(ebp+8) ")")
35464     }
35465 $emit-subx-var-as-rm32:end:
35466     # . restore registers
35467     5e/pop-to-esi
35468     59/pop-to-ecx
35469     58/pop-to-eax
35470     # . epilogue
35471     89/<- %esp 5/r32/ebp
35472     5d/pop-to-ebp
35473     c3/return
35474 
35475 find-matching-primitive:  # primitives: (addr primitive), stmt: (addr stmt) -> result/eax: (addr primitive)
35476     # . prologue
35477     55/push-ebp
35478     89/<- %ebp 4/r32/esp
35479     # . save registers
35480     51/push-ecx
35481     # var curr/ecx: (addr primitive) = primitives
35482     8b/-> *(ebp+8) 1/r32/ecx
35483     {
35484 $find-matching-primitive:loop:
35485       # if (curr == null) break
35486       81 7/subop/compare %ecx 0/imm32
35487       74/jump-if-= break/disp8
35488       # if match(curr, stmt) return curr
35489       {
35490         (mu-stmt-matches-primitive? *(ebp+0xc) %ecx)  # => eax
35491         3d/compare-eax-and 0/imm32/false
35492         74/jump-if-= break/disp8
35493         89/<- %eax 1/r32/ecx
35494         eb/jump $find-matching-primitive:end/disp8
35495       }
35496 $find-matching-primitive:next-primitive:
35497       # curr = curr->next
35498       (lookup *(ecx+0x3c) *(ecx+0x40))  # Primitive-next Primitive-next => eax
35499       89/<- %ecx 0/r32/eax
35500       #
35501       e9/jump loop/disp32
35502     }
35503     # return null
35504     b8/copy-to-eax 0/imm32
35505 $find-matching-primitive:end:
35506     # . restore registers
35507     59/pop-to-ecx
35508     # . epilogue
35509     89/<- %esp 5/r32/ebp
35510     5d/pop-to-ebp
35511     c3/return
35512 
35513 mu-stmt-matches-primitive?:  # stmt: (addr stmt), primitive: (addr primitive) -> result/eax: boolean
35514     # A mu stmt matches a primitive if the name matches, all the inout vars
35515     # match, and all the output vars match.
35516     # Vars match if types match and registers match.
35517     # In addition, a stmt output matches a primitive's output if types match
35518     # and the primitive has a wildcard register.
35519     # . prologue
35520     55/push-ebp
35521     89/<- %ebp 4/r32/esp
35522     # . save registers
35523     51/push-ecx
35524     52/push-edx
35525     53/push-ebx
35526     56/push-esi
35527     57/push-edi
35528     # ecx = stmt
35529     8b/-> *(ebp+8) 1/r32/ecx
35530     # edx = primitive
35531     8b/-> *(ebp+0xc) 2/r32/edx
35532     {
35533 $mu-stmt-matches-primitive?:check-name:
35534       # if (primitive->name != stmt->operation) return false
35535       # . var esi: (addr array byte) = lookup(stmt->operation)
35536       (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
35537       89/<- %esi 0/r32/eax
35538       # . var edi: (addr array byte) = lookup(primitive->name)
35539       (lookup *edx *(edx+4))  # Primitive-name Primitive-name => eax
35540 #?       (write-buffered Stderr %eax)
35541 #?       (write-buffered Stderr Newline)
35542 #?       (flush Stderr)
35543       89/<- %edi 0/r32/eax
35544       (string-equal? %esi %edi)  # => eax
35545       3d/compare-eax-and 0/imm32/false
35546       75/jump-if-!= break/disp8
35547       b8/copy-to-eax 0/imm32
35548       e9/jump $mu-stmt-matches-primitive?:end/disp32
35549     }
35550     # var curr/esi: (addr stmt-var) = lookup(stmt->inouts)
35551     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
35552     89/<- %esi 0/r32/eax
35553     # var curr2/edi: (addr list var) = lookup(primitive->inouts)
35554     (lookup *(edx+8) *(edx+0xc))  # Primitive-inouts Primitive-inouts => eax
35555     89/<- %edi 0/r32/eax
35556     {
35557 $mu-stmt-matches-primitive?:inouts-loop:
35558       # if (curr == 0 && curr2 == 0) move on to check outputs
35559       {
35560 $mu-stmt-matches-primitive?:check-both-inouts-null:
35561         81 7/subop/compare %esi 0/imm32
35562         75/jump-if-!= break/disp8
35563 $mu-stmt-matches-primitive?:stmt-inout-null:
35564         81 7/subop/compare %edi 0/imm32
35565         0f 84/jump-if-= $mu-stmt-matches-primitive?:check-outputs/disp32
35566 $mu-stmt-matches-primitive?:stmt-inout-null-and-prim-inout-not-null:
35567         # return false
35568         b8/copy-to-eax 0/imm32/false
35569         e9/jump $mu-stmt-matches-primitive?:end/disp32
35570       }
35571       # if (curr2 == 0) return false
35572       {
35573 $mu-stmt-matches-primitive?:check-prim-inout-null:
35574         81 7/subop/compare %edi 0/imm32
35575         75/jump-if-!= break/disp8
35576 $mu-stmt-matches-primitive?:prim-inout-null:
35577         b8/copy-to-eax 0/imm32/false
35578         e9/jump $mu-stmt-matches-primitive?:end/disp32
35579       }
35580       # if (curr != curr2) return false
35581       {
35582 $mu-stmt-matches-primitive?:check-inouts-match:
35583         (lookup *edi *(edi+4))  # List-value List-value => eax
35584         (operand-matches-primitive? %esi %eax)  # => eax
35585         3d/compare-eax-and 0/imm32/false
35586         75/jump-if-!= break/disp8
35587 $mu-stmt-matches-primitive?:inouts-match:
35588         b8/copy-to-eax 0/imm32/false
35589         e9/jump $mu-stmt-matches-primitive?:end/disp32
35590       }
35591 $mu-stmt-matches-primitive?:next-inout:
35592       # curr = lookup(curr->next)
35593       (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
35594       89/<- %esi 0/r32/eax
35595       # curr2 = lookup(curr2->next)
35596       (lookup *(edi+8) *(edi+0xc))  # List-next List-next => eax
35597       89/<- %edi 0/r32/eax
35598       #
35599       e9/jump loop/disp32
35600     }
35601 $mu-stmt-matches-primitive?:check-outputs:
35602     # var curr/esi: (addr stmt-var) = lookup(stmt->outputs)
35603     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
35604     89/<- %esi 0/r32/eax
35605     # var curr2/edi: (addr list var) = lookup(primitive->outputs)
35606     (lookup *(edx+0x10) *(edx+0x14))  # Primitive-outputs Primitive-outputs => eax
35607     89/<- %edi 0/r32/eax
35608     {
35609 $mu-stmt-matches-primitive?:outputs-loop:
35610       # if (curr == 0) return (curr2 == 0)
35611       {
35612 $mu-stmt-matches-primitive?:check-both-outputs-null:
35613         81 7/subop/compare %esi 0/imm32
35614         75/jump-if-!= break/disp8
35615         {
35616 $mu-stmt-matches-primitive?:stmt-output-null:
35617           81 7/subop/compare %edi 0/imm32
35618           75/jump-if-!= break/disp8
35619 $mu-stmt-matches-primitive?:both-outputs-null:
35620           # return true
35621           b8/copy-to-eax 1/imm32
35622           e9/jump $mu-stmt-matches-primitive?:end/disp32
35623         }
35624 $mu-stmt-matches-primitive?:stmt-output-null-and-prim-output-not-null:
35625         # return false
35626         b8/copy-to-eax 0/imm32
35627         e9/jump $mu-stmt-matches-primitive?:end/disp32
35628       }
35629       # if (curr2 == 0) return false
35630       {
35631 $mu-stmt-matches-primitive?:check-prim-output-null:
35632         81 7/subop/compare %edi 0/imm32
35633         75/jump-if-!= break/disp8
35634 $mu-stmt-matches-primitive?:prim-output-is-null:
35635         b8/copy-to-eax 0/imm32
35636         e9/jump $mu-stmt-matches-primitive?:end/disp32
35637       }
35638       # if (curr != curr2) return false
35639       {
35640 $mu-stmt-matches-primitive?:check-outputs-match:
35641         (lookup *edi *(edi+4))  # List-value List-value => eax
35642         (operand-matches-primitive? %esi %eax)  # => eax
35643         3d/compare-eax-and 0/imm32/false
35644         75/jump-if-!= break/disp8
35645 $mu-stmt-matches-primitive?:outputs-match:
35646         b8/copy-to-eax 0/imm32
35647         e9/jump $mu-stmt-matches-primitive?:end/disp32
35648       }
35649 $mu-stmt-matches-primitive?:next-output:
35650       # curr = lookup(curr->next)
35651       (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
35652       89/<- %esi 0/r32/eax
35653       # curr2 = lookup(curr2->next)
35654       (lookup *(edi+8) *(edi+0xc))  # List-next List-next => eax
35655       89/<- %edi 0/r32/eax
35656       #
35657       e9/jump loop/disp32
35658     }
35659 $mu-stmt-matches-primitive?:return-true:
35660     b8/copy-to-eax 1/imm32
35661 $mu-stmt-matches-primitive?:end:
35662     # . restore registers
35663     5f/pop-to-edi
35664     5e/pop-to-esi
35665     5b/pop-to-ebx
35666     5a/pop-to-edx
35667     59/pop-to-ecx
35668     # . epilogue
35669     89/<- %esp 5/r32/ebp
35670     5d/pop-to-ebp
35671     c3/return
35672 
35673 operand-matches-primitive?:  # s: (addr stmt-var), prim-var: (addr var) -> result/eax: boolean
35674     # . prologue
35675     55/push-ebp
35676     89/<- %ebp 4/r32/esp
35677     # . save registers
35678     51/push-ecx
35679     52/push-edx
35680     53/push-ebx
35681     56/push-esi
35682     57/push-edi
35683     # ecx = s
35684     8b/-> *(ebp+8) 1/r32/ecx
35685     # var var/esi: (addr var) = lookup(s->value)
35686     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
35687     89/<- %esi 0/r32/eax
35688     # edi = prim-var
35689     8b/-> *(ebp+0xc) 7/r32/edi
35690 $operand-matches-primitive?:check-type:
35691     # if !category-match?(var->type, prim-var->type) return false
35692     # . var vtype/ebx: (addr type-tree) = lookup(var->type)
35693     (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
35694     89/<- %ebx 0/r32/eax
35695     # . if s is deref, vtype = vtype->right
35696     {
35697       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
35698       74/jump-if-= break/disp8
35699 $operand-matches-primitive?:is-deref:
35700       # . var t/eax: (addr type)
35701       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
35702       # . if !t->is-atom? t = t->left
35703       81 7/subop/compare *eax 0/imm32/false
35704       {
35705         75/jump-if-!= break/disp8
35706         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
35707       }
35708       # .
35709       89/<- %ebx 0/r32/eax
35710     }
35711     # . var ptype/eax: (addr type-tree) = lookup(prim-var->type)
35712     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
35713     (subx-type-category-match? %ebx %eax)  # => eax
35714     3d/compare-eax-and 0/imm32/false
35715     0f 84/jump-if-= $operand-matches-primitive?:return-false/disp32
35716     {
35717 $operand-matches-primitive?:check-register:
35718       # if prim-var is in memory and var is in register but dereference, match
35719       {
35720         81 7/subop/compare *(edi+0x18) 0/imm32  # Var-register
35721         0f 85/jump-if-!= break/disp32
35722         81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
35723         74/jump-if-= break/disp8
35724         81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
35725         74/jump-if-= break/disp8
35726 $operand-matches-primitive?:var-deref-match:
35727         e9/jump $operand-matches-primitive?:return-true/disp32
35728       }
35729       # if prim-var is in register and var is in register but dereference, no match
35730       {
35731         81 7/subop/compare *(edi+0x18) 0/imm32  # Var-register
35732         0f 84/jump-if-= break/disp32
35733         81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
35734         0f 84/jump-if-= break/disp32
35735         81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
35736         74/jump-if-= break/disp8
35737 $operand-matches-primitive?:var-deref-no-match:
35738         e9/jump $operand-matches-primitive?:return-false/disp32
35739       }
35740       # return false if var->register doesn't match prim-var->register
35741       {
35742         # if register addresses are equal, it's a match
35743         # var vreg/ebx: (addr array byte) = lookup(var->register)
35744         (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
35745         89/<- %ebx 0/r32/eax
35746         # var preg/ecx: (addr array byte) = lookup(prim-var->register)
35747         (lookup *(edi+0x18) *(edi+0x1c))  # Var-register Var-register => eax
35748         89/<- %ecx 0/r32/eax
35749         # if (vreg == preg) break
35750         39/compare %ecx 3/r32/ebx
35751         74/jump-if-= break/disp8
35752 $operand-matches-primitive?:var-register-no-match:
35753         # if either address is 0, return false
35754         81 7/subop/compare %ebx 0/imm32
35755         74/jump-if-=  $operand-matches-primitive?:return-false/disp8
35756         81 7/subop/compare %ecx 0/imm32
35757         74/jump-if-=  $operand-matches-primitive?:return-false/disp8
35758         # if prim-var->register is wildcard, it's a match
35759         (string-equal? %ecx "*")  # Any-register => eax
35760         3d/compare-eax-and 0/imm32/false
35761         75/jump-if-!= break/disp8
35762 $operand-matches-primitive?:wildcard-no-match:
35763         # if string contents aren't equal, return false
35764         (string-equal? %ecx %ebx)  # => eax
35765         3d/compare-eax-and 0/imm32/false
35766         74/jump-if-= $operand-matches-primitive?:return-false/disp8
35767       }
35768     }
35769 $operand-matches-primitive?:return-true:
35770     b8/copy-to-eax 1/imm32/true
35771     eb/jump $operand-matches-primitive?:end/disp8
35772 $operand-matches-primitive?:return-false:
35773     b8/copy-to-eax 0/imm32/false
35774 $operand-matches-primitive?:end:
35775     # . restore registers
35776     5f/pop-to-edi
35777     5e/pop-to-esi
35778     5b/pop-to-ebx
35779     5a/pop-to-edx
35780     59/pop-to-ecx
35781     # . epilogue
35782     89/<- %esp 5/r32/ebp
35783     5d/pop-to-ebp
35784     c3/return
35785 
35786 find-matching-function:  # functions: (addr function), stmt: (addr stmt) -> result/eax: (addr function)
35787     # . prologue
35788     55/push-ebp
35789     89/<- %ebp 4/r32/esp
35790     # . save registers
35791     51/push-ecx
35792     # var curr/ecx: (handle function) = functions
35793     8b/-> *(ebp+8) 1/r32/ecx
35794     {
35795       # if (curr == null) break
35796       81 7/subop/compare %ecx 0/imm32
35797       74/jump-if-= break/disp8
35798 #?       (write-buffered Stderr "iter\n")
35799 #?       (flush Stderr)
35800       # if match(stmt, curr) return curr
35801       {
35802         (mu-stmt-matches-function? *(ebp+0xc) %ecx)  # => eax
35803         3d/compare-eax-and 0/imm32/false
35804         74/jump-if-= break/disp8
35805         89/<- %eax 1/r32/ecx
35806         eb/jump $find-matching-function:end/disp8
35807       }
35808       # curr = curr->next
35809       (lookup *(ecx+0x20) *(ecx+0x24))  # Function-next Function-next => eax
35810       89/<- %ecx 0/r32/eax
35811       #
35812       eb/jump loop/disp8
35813     }
35814     # return null
35815     b8/copy-to-eax 0/imm32
35816 $find-matching-function:end:
35817     # . restore registers
35818     59/pop-to-ecx
35819     # . epilogue
35820     89/<- %esp 5/r32/ebp
35821     5d/pop-to-ebp
35822     c3/return
35823 
35824 # Just compare names; user-defined functions don't support overloading yet.
35825 mu-stmt-matches-function?:  # stmt: (addr stmt1), function: (addr function) -> result/eax: boolean
35826     # . prologue
35827     55/push-ebp
35828     89/<- %ebp 4/r32/esp
35829     # . save registers
35830     51/push-ecx
35831     # return function->name == stmt->operation
35832     # ecx = lookup(stmt->operation)
35833     8b/-> *(ebp+8) 0/r32/eax
35834     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
35835     89/<- %ecx 0/r32/eax
35836     # eax = lookup(function->name)
35837     8b/-> *(ebp+0xc) 0/r32/eax
35838     (lookup *eax *(eax+4))  # Function-name Function-name => eax
35839     (string-equal? %eax %ecx)  # => eax
35840 $mu-stmt-matches-function?:end:
35841     # . restore registers
35842     59/pop-to-ecx
35843     # . epilogue
35844     89/<- %esp 5/r32/ebp
35845     5d/pop-to-ebp
35846     c3/return
35847 
35848 # Type-checking happens elsewhere. This method is for selecting between
35849 # primitives.
35850 subx-type-category-match?:  # a: (addr type-tree), b: (addr type-tree) -> result/eax: boolean
35851     # . prologue
35852     55/push-ebp
35853     89/<- %ebp 4/r32/esp
35854     # . save registers
35855     51/push-ecx
35856     # var cata/ecx: int = type-category(a)
35857     (type-category *(ebp+8))  # => eax
35858     89/<- %ecx 0/r32/eax
35859     # var catb/eax: int = type-category(b)
35860     (type-category *(ebp+0xc))  # => eax
35861     # return cata == catb
35862     39/compare %eax 1/r32/ecx
35863     0f 94/set-byte-if-= %al
35864     81 4/subop/and %eax 0xff/imm32
35865 $subx-type-category-match?:end:
35866     # . restore registers
35867     59/pop-to-ecx
35868     # . epilogue
35869     89/<- %esp 5/r32/ebp
35870     5d/pop-to-ebp
35871     c3/return
35872 
35873 type-category:  # a: (addr type-tree) -> result/eax: int
35874     # . prologue
35875     55/push-ebp
35876     89/<- %ebp 4/r32/esp
35877     # . save registers
35878     51/push-ecx
35879     # var lit?/ecx: boolean = literal-type?(a)
35880     (simple-mu-type? *(ebp+8) 0)  # literal => eax
35881     89/<- %ecx 0/r32/eax
35882     # var float?/eax: int = float?(a)
35883     (simple-mu-type? *(ebp+8) 0xf)  # => eax
35884     # set bits for lit? and float?
35885     c1/shift 4/subop/left %ecx 1/imm8
35886     09/or %eax 1/r32/ecx
35887 $type-category:end:
35888     # . restore registers
35889     59/pop-to-ecx
35890     # . epilogue
35891     89/<- %esp 5/r32/ebp
35892     5d/pop-to-ebp
35893     c3/return
35894 
35895 simple-mu-type?:  # a: (addr type-tree), n: type-id -> result/eax: boolean
35896     # . prologue
35897     55/push-ebp
35898     89/<- %ebp 4/r32/esp
35899     # . save registers
35900     51/push-ecx
35901     # ecx = n
35902     8b/-> *(ebp+0xc) 1/r32/ecx
35903     # return (a->value == n)
35904     8b/-> *(ebp+8) 0/r32/eax
35905     39/compare *(eax+4) 1/r32/ecx  # Type-tree-value
35906     0f 94/set-byte-if-= %al
35907     81 4/subop/and %eax 0xff/imm32
35908 $simple-mu-type?:end:
35909     # . restore registers
35910     59/pop-to-ecx
35911     # . epilogue
35912     89/<- %esp 5/r32/ebp
35913     5d/pop-to-ebp
35914     c3/return
35915 
35916 mu-addr-type?:  # a: (addr type-tree) -> result/eax: boolean
35917     # . prologue
35918     55/push-ebp
35919     89/<- %ebp 4/r32/esp
35920     # eax = a
35921     8b/-> *(ebp+8) 0/r32/eax
35922     # if (!a->is-atom?) a = a->left
35923     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
35924     {
35925       75/jump-if-!= break/disp8
35926       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
35927     }
35928     # return (a->value == addr)
35929     81 7/subop/compare *(eax+4) 2/imm32/addr  # Type-tree-value
35930     0f 94/set-byte-if-= %al
35931     81 4/subop/and %eax 0xff/imm32
35932 $mu-addr-type?:end:
35933     # . epilogue
35934     89/<- %esp 5/r32/ebp
35935     5d/pop-to-ebp
35936     c3/return
35937 
35938 mu-array-type?:  # a: (addr type-tree) -> result/eax: boolean
35939     # . prologue
35940     55/push-ebp
35941     89/<- %ebp 4/r32/esp
35942     # eax = a
35943     8b/-> *(ebp+8) 0/r32/eax
35944     # if (!a->is-atom?) a = a->left
35945     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
35946     {
35947       75/jump-if-!= break/disp8
35948       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
35949     }
35950     # return (a->value == array)
35951     81 7/subop/compare *(eax+4) 3/imm32/array  # Type-tree-value
35952     0f 94/set-byte-if-= %al
35953     81 4/subop/and %eax 0xff/imm32
35954 $mu-array-type?:end:
35955     # . epilogue
35956     89/<- %esp 5/r32/ebp
35957     5d/pop-to-ebp
35958     c3/return
35959 
35960 mu-string-type?:  # a: (addr type-tree) -> result/eax: boolean
35961     # . prologue
35962     55/push-ebp
35963     89/<- %ebp 4/r32/esp
35964     # . save registers
35965     56/push-esi
35966     # esi = a
35967     8b/-> *(ebp+8) 6/r32/esi
35968     # if (a->is-atom?) return false
35969     81 7/subop/compare *esi 0/imm32/false  # Type-tree-is-atom
35970     0f 85/jump-if-!= $mu-string-type?:return-false/disp32
35971     # if a is not an addr, return false
35972     (mu-addr-type? %esi)  # => eax
35973     3d/compare-eax-with 0/imm32/false
35974     0f 84/jump-if-= $mu-string-type?:end/disp32  # eax changes var
35975     # if a is not an array, return false
35976     (lookup *(esi+0xc) *(esi+0x10))  # Type-tree-right Type-tree-right => eax
35977     (mu-array-type? %eax)  # => eax
35978     3d/compare-eax-with 0/imm32/false
35979     74/jump-if-= $mu-string-type?:end/disp8  # eax changes var
35980     # var p/eax: (addr type-tree) = payload of a
35981     (lookup *(esi+0xc) *(esi+0x10))  # Type-tree-right Type-tree-right => eax
35982     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
35983     # if p is an atom, return false
35984     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
35985     75/jump-if-!= $mu-string-type?:return-false/disp8
35986     # return (p == byte)
35987     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
35988     (simple-mu-type? %eax 8)  # byte => eax
35989     eb/jump $mu-string-type?:end/disp8
35990 $mu-string-type?:return-false:
35991     b8/copy-to-eax 0/imm32/false
35992 $mu-string-type?:end:
35993     # . restore registers
35994     5e/pop-to-esi
35995     # . epilogue
35996     89/<- %esp 5/r32/ebp
35997     5d/pop-to-ebp
35998     c3/return
35999 
36000 mu-stream-type?:  # a: (addr type-tree) -> result/eax: boolean
36001     # . prologue
36002     55/push-ebp
36003     89/<- %ebp 4/r32/esp
36004     # eax = a
36005     8b/-> *(ebp+8) 0/r32/eax
36006     # if (!a->is-atom?) a = a->left
36007     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
36008     {
36009       75/jump-if-!= break/disp8
36010       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
36011     }
36012     # return (a->value == stream)
36013     81 7/subop/compare *(eax+4) 0xb/imm32/stream  # Type-tree-value
36014     0f 94/set-byte-if-= %al
36015     81 4/subop/and %eax 0xff/imm32
36016 $mu-stream-type?:end:
36017     # . epilogue
36018     89/<- %esp 5/r32/ebp
36019     5d/pop-to-ebp
36020     c3/return
36021 
36022 test-emit-subx-stmt-primitive:
36023     # Primitive operation on a variable on the stack.
36024     #   increment foo
36025     # =>
36026     #   ff 0/subop/increment *(ebp-8)
36027     #
36028     # There's a variable on the var stack as follows:
36029     #   name: 'foo'
36030     #   type: int
36031     #   stack-offset: -8
36032     #
36033     # There's a primitive with this info:
36034     #   name: 'increment'
36035     #   inouts: int/mem
36036     #   value: 'ff 0/subop/increment'
36037     #
36038     # . prologue
36039     55/push-ebp
36040     89/<- %ebp 4/r32/esp
36041     # setup
36042     (clear-stream _test-output-stream)
36043     (clear-stream $_test-output-buffered-file->buffer)
36044     # simulate allocated payloads starting with an initial fake alloc-id (0x11)
36045 $test-emit-subx-stmt-primitive:initialize-type:
36046     # var type/ecx: (payload type-tree) = int
36047     68/push 0/imm32/right:null
36048     68/push 0/imm32/right:null
36049     68/push 0/imm32/left:unused
36050     68/push 1/imm32/value:int
36051     68/push 1/imm32/is-atom?:true
36052     68/push 0x11/imm32/alloc-id:fake:payload
36053     89/<- %ecx 4/r32/esp
36054 $test-emit-subx-stmt-primitive:initialize-var:
36055     # var var-foo/ecx: (payload var) = var(type)
36056     68/push 0/imm32/no-register
36057     68/push 0/imm32/no-register
36058     68/push -8/imm32/stack-offset
36059     68/push 1/imm32/block-depth
36060     51/push-ecx/type
36061     68/push 0x11/imm32/alloc-id:fake
36062     68/push 0/imm32/name
36063     68/push 0/imm32/name
36064     68/push 0x11/imm32/alloc-id:fake:payload
36065     89/<- %ecx 4/r32/esp
36066 $test-emit-subx-stmt-primitive:initialize-var-name:
36067     # var-foo->name = "foo"
36068     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
36069     (copy-array Heap "foo" %eax)
36070 $test-emit-subx-stmt-primitive:initialize-stmt-var:
36071     # var operand/ebx: (payload stmt-var) = stmt-var(var-foo)
36072     68/push 0/imm32/is-deref:false
36073     68/push 0/imm32/next
36074     68/push 0/imm32/next
36075     51/push-ecx/var-foo
36076     68/push 0x11/imm32/alloc-id:fake
36077     68/push 0x11/imm32/alloc-id:fake:payload
36078     89/<- %ebx 4/r32/esp
36079 $test-emit-subx-stmt-primitive:initialize-stmt:
36080     # var stmt/esi: (addr statement)
36081     68/push 0/imm32/no-outputs
36082     68/push 0/imm32/no-outputs
36083     53/push-ebx/inouts
36084     68/push 0x11/imm32/alloc-id:fake
36085     68/push 0/imm32/operation
36086     68/push 0/imm32/operation
36087     68/push 1/imm32/tag
36088     89/<- %esi 4/r32/esp
36089 $test-emit-subx-stmt-primitive:initialize-stmt-operation:
36090     # stmt->operation = "increment"
36091     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
36092     (copy-array Heap "increment" %eax)
36093 $test-emit-subx-stmt-primitive:initialize-primitive:
36094     # var primitives/ebx: (addr primitive)
36095     68/push 0/imm32/next
36096     68/push 0/imm32/next
36097     68/push 0/imm32/no-x32
36098     68/push 0/imm32/no-xm32
36099     68/push 0/imm32/no-disp32
36100     68/push 0/imm32/no-imm8
36101     68/push 0/imm32/no-imm32
36102     68/push 0/imm32/no-r32
36103     68/push 1/imm32/rm32-is-first-inout
36104     68/push 0/imm32/subx-name
36105     68/push 0/imm32/subx-name
36106     68/push 0/imm32/no-outputs
36107     68/push 0/imm32/no-outputs
36108     53/push-ebx/inouts  # hack: reuse stmt-var from call stmt as (list var) in function declaration
36109     68/push 0x11/imm32/alloc-id:fake
36110     68/push 0/imm32/name
36111     68/push 0/imm32/name
36112     89/<- %ebx 4/r32/esp
36113 $test-emit-subx-stmt-primitive:initialize-primitive-name:
36114     # primitives->name = "increment"
36115     (copy-array Heap "increment" %ebx)  # Primitive-name
36116 $test-emit-subx-stmt-primitive:initialize-primitive-subx-name:
36117     # primitives->subx-name = "ff 0/subop/increment"
36118     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
36119     (copy-array Heap "ff 0/subop/increment" %eax)
36120     # convert
36121     c7 0/subop/copy *Curr-block-depth 0/imm32
36122     (emit-subx-stmt _test-output-buffered-file %esi %ebx 0 Stderr 0)
36123     (flush _test-output-buffered-file)
36124 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
36130     # check output
36131     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment *(ebp+0xfffffff8)" "F - test-emit-subx-stmt-primitive")
36132     # . epilogue
36133     89/<- %esp 5/r32/ebp
36134     5d/pop-to-ebp
36135     c3/return
36136 
36137 test-emit-subx-stmt-primitive-register:
36138     # Primitive operation on a variable in a register.
36139     #   foo <- increment
36140     # =>
36141     #   ff 0/subop/increment %eax  # sub-optimal, but should suffice
36142     #
36143     # There's a variable on the var stack as follows:
36144     #   name: 'foo'
36145     #   type: int
36146     #   register: 'eax'
36147     #
36148     # There's a primitive with this info:
36149     #   name: 'increment'
36150     #   out: int/reg
36151     #   value: 'ff 0/subop/increment'
36152     #
36153     # . prologue
36154     55/push-ebp
36155     89/<- %ebp 4/r32/esp
36156     # setup
36157     (clear-stream _test-output-stream)
36158     (clear-stream $_test-output-buffered-file->buffer)
36159 $test-emit-subx-stmt-primitive-register:initialize-type:
36160     # var type/ecx: (payload type-tree) = int
36161     68/push 0/imm32/right:null
36162     68/push 0/imm32/right:null
36163     68/push 0/imm32/left:unused
36164     68/push 1/imm32/value:int
36165     68/push 1/imm32/is-atom?:true
36166     68/push 0x11/imm32/alloc-id:fake:payload
36167     89/<- %ecx 4/r32/esp
36168 $test-emit-subx-stmt-primitive-register:initialize-var:
36169     # var var-foo/ecx: (payload var)
36170     68/push 0/imm32/register
36171     68/push 0/imm32/register
36172     68/push 0/imm32/no-stack-offset
36173     68/push 1/imm32/block-depth
36174     51/push-ecx
36175     68/push 0x11/imm32/alloc-id:fake
36176     68/push 0/imm32/name
36177     68/push 0/imm32/name
36178     68/push 0x11/imm32/alloc-id:fake:payload
36179     89/<- %ecx 4/r32/esp
36180 $test-emit-subx-stmt-primitive-register:initialize-var-name:
36181     # var-foo->name = "foo"
36182     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
36183     (copy-array Heap "foo" %eax)
36184 $test-emit-subx-stmt-primitive-register:initialize-var-register:
36185     # var-foo->register = "eax"
36186     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
36187     (copy-array Heap "eax" %eax)
36188 $test-emit-subx-stmt-primitive-register:initialize-stmt-var:
36189     # var operand/ebx: (payload stmt-var)
36190     68/push 0/imm32/is-deref:false
36191     68/push 0/imm32/next
36192     68/push 0/imm32/next
36193     51/push-ecx/var-foo
36194     68/push 0x11/imm32/alloc-id:fake
36195     68/push 0x11/imm32/alloc-id:fake:payload
36196     89/<- %ebx 4/r32/esp
36197 $test-emit-subx-stmt-primitive-register:initialize-stmt:
36198     # var stmt/esi: (addr statement)
36199     53/push-ebx/outputs
36200     68/push 0x11/imm32/alloc-id:fake
36201     68/push 0/imm32/no-inouts
36202     68/push 0/imm32/no-inouts
36203     68/push 0/imm32/operation
36204     68/push 0/imm32/operation
36205     68/push 1/imm32
36206     89/<- %esi 4/r32/esp
36207 $test-emit-subx-stmt-primitive-register:initialize-stmt-operation:
36208     # stmt->operation = "increment"
36209     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
36210     (copy-array Heap "increment" %eax)
36211 $test-emit-subx-stmt-primitive-register:initialize-formal-var:
36212     # var formal-var/ebx: (payload var)
36213     68/push 0/imm32/register
36214     68/push 0/imm32/register
36215     68/push 0/imm32/no-stack-offset
36216     68/push 1/imm32/block-depth
36217     ff 6/subop/push *(ecx+0x10)  # Var-type + payload alloc id + handle alloc id
36218     68/push 0x11/imm32/alloc-id:fake
36219     68/push 0/imm32/name
36220     68/push 0/imm32/name
36221     68/push 0x11/imm32/alloc-id:fake:payload
36222     89/<- %ebx 4/r32/esp
36223 $test-emit-subx-stmt-primitive-register:initialize-formal-var-name:
36224     # formal-var->name = "dummy"
36225     8d/copy-address *(ebx+4) 0/r32/eax  # Var-name + 4
36226     (copy-array Heap "dummy" %eax)
36227 $test-emit-subx-stmt-primitive-register:initialize-formal-register:
36228     # formal-var->register = "*"
36229     8d/copy-address *(ebx+0x1c) 0/r32/eax  # Var-register + 4
36230     (copy-array Heap "*" %eax)  # Any-register
36231 $test-emit-subx-stmt-primitive-register:initialize-var-list:
36232     # var formal-outputs/ebx: (payload list var)
36233     68/push 0/imm32/next
36234     68/push 0/imm32/next
36235     53/push-ebx/formal-var
36236     68/push 0x11/imm32/alloc-id:fake
36237     68/push 0x11/imm32/alloc-id:fake:payload
36238     89/<- %ebx 4/r32/esp
36239 $test-emit-subx-stmt-primitive-register:initialize-primitive:
36240     # var primitives/ebx: (addr primitive)
36241     68/push 0/imm32/next
36242     68/push 0/imm32/next
36243     68/push 0/imm32/no-x32
36244     68/push 0/imm32/no-xm32
36245     68/push 0/imm32/no-disp32
36246     68/push 0/imm32/no-imm8
36247     68/push 0/imm32/no-imm32
36248     68/push 0/imm32/no-r32
36249     68/push 3/imm32/rm32-is-first-output
36250     68/push 0/imm32/subx-name
36251     68/push 0/imm32/subx-name
36252     53/push-ebx/outputs
36253     68/push 0x11/imm32/alloc-id:fake
36254     68/push 0/imm32/no-inouts
36255     68/push 0/imm32/no-inouts
36256     68/push 0/imm32/name
36257     68/push 0/imm32/name
36258     89/<- %ebx 4/r32/esp
36259 $test-emit-subx-stmt-primitive-register:initialize-primitive-name:
36260     # primitives->name = "increment"
36261     (copy-array Heap "increment" %ebx)  # Primitive-name
36262 $test-emit-subx-stmt-primitive-register:initialize-primitive-subx-name:
36263     # primitives->subx-name = "ff 0/subop/increment"
36264     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
36265     (copy-array Heap "ff 0/subop/increment" %eax)
36266     # convert
36267     c7 0/subop/copy *Curr-block-depth 0/imm32
36268     (emit-subx-stmt _test-output-buffered-file %esi %ebx 0 Stderr 0)
36269     (flush _test-output-buffered-file)
36270 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
36276     # check output
36277     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-primitive-register")
36278     # . epilogue
36279     89/<- %esp 5/r32/ebp
36280     5d/pop-to-ebp
36281     c3/return
36282 
36283 test-emit-subx-stmt-select-primitive:
36284     # Select the right primitive between overloads.
36285     #   foo <- increment
36286     # =>
36287     #   ff 0/subop/increment %eax  # sub-optimal, but should suffice
36288     #
36289     # There's a variable on the var stack as follows:
36290     #   name: 'foo'
36291     #   type: int
36292     #   register: 'eax'
36293     #
36294     # There's two primitives, as follows:
36295     #   - name: 'increment'
36296     #     out: int/reg
36297     #     value: 'ff 0/subop/increment'
36298     #   - name: 'increment'
36299     #     inout: int/mem
36300     #     value: 'ff 0/subop/increment'
36301     #
36302     # . prologue
36303     55/push-ebp
36304     89/<- %ebp 4/r32/esp
36305     # setup
36306     (clear-stream _test-output-stream)
36307     (clear-stream $_test-output-buffered-file->buffer)
36308 $test-emit-subx-stmt-select-primitive:initialize-type:
36309     # var type/ecx: (payload type-tree) = int
36310     68/push 0/imm32/right:null
36311     68/push 0/imm32/right:null
36312     68/push 0/imm32/left:unused
36313     68/push 1/imm32/value:int
36314     68/push 1/imm32/is-atom?:true
36315     68/push 0x11/imm32/alloc-id:fake:payload
36316     89/<- %ecx 4/r32/esp
36317 $test-emit-subx-stmt-select-primitive:initialize-var:
36318     # var var-foo/ecx: (payload var)
36319     68/push 0/imm32/register
36320     68/push 0/imm32/register
36321     68/push 0/imm32/no-stack-offset
36322     68/push 1/imm32/block-depth
36323     51/push-ecx
36324     68/push 0x11/imm32/alloc-id:fake
36325     68/push 0/imm32/name
36326     68/push 0/imm32/name
36327     68/push 0x11/imm32/alloc-id:fake:payload
36328     89/<- %ecx 4/r32/esp
36329 $test-emit-subx-stmt-select-primitive:initialize-var-name:
36330     # var-foo->name = "foo"
36331     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
36332     (copy-array Heap "foo" %eax)
36333 $test-emit-subx-stmt-select-primitive:initialize-var-register:
36334     # var-foo->register = "eax"
36335     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
36336     (copy-array Heap "eax" %eax)
36337 $test-emit-subx-stmt-select-primitive:initialize-stmt-var:
36338     # var operand/ebx: (payload stmt-var)
36339     68/push 0/imm32/is-deref:false
36340     68/push 0/imm32/next
36341     68/push 0/imm32/next
36342     51/push-ecx/var-foo
36343     68/push 0x11/imm32/alloc-id:fake
36344     68/push 0x11/imm32/alloc-id:fake:payload
36345     89/<- %ebx 4/r32/esp
36346 $test-emit-subx-stmt-select-primitive:initialize-stmt:
36347     # var stmt/esi: (addr statement)
36348     53/push-ebx/outputs
36349     68/push 0x11/imm32/alloc-id:fake
36350     68/push 0/imm32/no-inouts
36351     68/push 0/imm32/no-inouts
36352     68/push 0/imm32/operation
36353     68/push 0/imm32/operation
36354     68/push 1/imm32
36355     89/<- %esi 4/r32/esp
36356 $test-emit-subx-stmt-select-primitive:initialize-stmt-operation:
36357     # stmt->operation = "increment"
36358     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
36359     (copy-array Heap "increment" %eax)
36360 $test-emit-subx-stmt-select-primitive:initialize-formal-var:
36361     # var formal-var/ebx: (payload var)
36362     68/push 0/imm32/register
36363     68/push 0/imm32/register
36364     68/push 0/imm32/no-stack-offset
36365     68/push 1/imm32/block-depth
36366     ff 6/subop/push *(ecx+0x10)  # Var-type + payload alloc id + handle alloc id
36367     68/push 0x11/imm32/alloc-id:fake
36368     68/push 0/imm32/name
36369     68/push 0/imm32/name
36370     68/push 0x11/imm32/alloc-id:fake:payload
36371     89/<- %ebx 4/r32/esp
36372 $test-emit-subx-stmt-select-primitive:initialize-formal-var-name:
36373     # formal-var->name = "dummy"
36374     8d/copy-address *(ebx+4) 0/r32/eax  # Var-name + 4
36375     (copy-array Heap "dummy" %eax)
36376 $test-emit-subx-stmt-select-primitive:initialize-formal-register:
36377     # formal-var->register = "*"
36378     8d/copy-address *(ebx+0x1c) 0/r32/eax  # Var-register + 4
36379     (copy-array Heap "*" %eax)  # Any-register
36380 $test-emit-subx-stmt-select-primitive:initialize-var-list:
36381     # var formal-outputs/ebx: (payload list var)
36382     68/push 0/imm32/next
36383     68/push 0/imm32/next
36384     53/push-ebx/formal-var
36385     68/push 0x11/imm32/alloc-id:fake
36386     68/push 0x11/imm32/alloc-id:fake:payload
36387     89/<- %ebx 4/r32/esp
36388 $test-emit-subx-stmt-select-primitive:initialize-primitive2:
36389     # var primitive2/edi: (payload primitive)
36390     68/push 0/imm32/next
36391     68/push 0/imm32/next
36392     68/push 0/imm32/no-x32
36393     68/push 0/imm32/no-xm32
36394     68/push 0/imm32/no-disp32
36395     68/push 0/imm32/no-imm8
36396     68/push 0/imm32/no-imm32
36397     68/push 0/imm32/no-r32
36398     68/push 3/imm32/rm32-is-first-output
36399     68/push 0/imm32/subx-name
36400     68/push 0/imm32/subx-name
36401     53/push-ebx/outputs
36402     68/push 0x11/imm32/alloc-id:fake
36403     68/push 0/imm32/no-inouts
36404     68/push 0/imm32/no-inouts
36405     68/push 0/imm32/name
36406     68/push 0/imm32/name
36407     68/push 0x11/imm32/alloc-id:fake:payload
36408     89/<- %edi 4/r32/esp
36409 $test-emit-subx-stmt-select-primitive:initialize-primitive2-name:
36410     # primitives->name = "increment"
36411     8d/copy-address *(edi+4) 0/r32/eax  # Primitive-name + 4
36412     (copy-array Heap "increment" %eax)
36413 $test-emit-subx-stmt-select-primitive:initialize-primitive2-subx-name:
36414     # primitives->subx-name = "ff 0/subop/increment"
36415     8d/copy-address *(edi+0x1c) 0/r32/eax  # Primitive-subx-name + 4
36416     (copy-array Heap "ff 0/subop/increment" %eax)
36417 $test-emit-subx-stmt-select-primitive:initialize-primitive:
36418     # var primitives/ebx: (addr primitive)
36419     57/push-edi
36420     68/push 0x11/imm32/alloc-id:fake
36421     68/push 0/imm32/no-x32
36422     68/push 0/imm32/no-xm32
36423     68/push 0/imm32/no-disp32
36424     68/push 0/imm32/no-imm8
36425     68/push 0/imm32/no-imm32
36426     68/push 0/imm32/no-r32
36427     68/push 1/imm32/rm32-is-first-inout
36428     68/push 0/imm32/subx-name
36429     68/push 0/imm32/subx-name
36430     68/push 0/imm32/no-outputs
36431     68/push 0/imm32/no-outputs
36432     53/push-ebx/inouts  # hack: reuse stmt-var from call stmt as (list var) in function declaration
36433     68/push 0x11/imm32/alloc-id:fake
36434     68/push 0/imm32/name
36435     68/push 0/imm32/name
36436     89/<- %ebx 4/r32/esp
36437 $test-emit-subx-stmt-select-primitive:initialize-primitive-name:
36438     # primitives->name = "increment"
36439     (copy-array Heap "increment" %ebx)  # Primitive-name
36440 $test-emit-subx-stmt-select-primitive:initialize-primitive-subx-name:
36441     # primitives->subx-name = "ff 0/subop/increment"
36442     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
36443     (copy-array Heap "ff 0/subop/increment" %eax)
36444     # convert
36445     c7 0/subop/copy *Curr-block-depth 0/imm32
36446     (emit-subx-stmt _test-output-buffered-file %esi %ebx 0 Stderr 0)
36447     (flush _test-output-buffered-file)
36448 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
36454     # check output
36455     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-select-primitive")
36456     # . epilogue
36457     89/<- %esp 5/r32/ebp
36458     5d/pop-to-ebp
36459     c3/return
36460 
36461 test-emit-subx-stmt-select-primitive-2:
36462     # Select the right primitive between overloads.
36463     #   increment foo
36464     # =>
36465     #   ff 0/subop/increment %eax  # sub-optimal, but should suffice
36466     #
36467     # There's a variable on the var stack as follows:
36468     #   name: 'foo'
36469     #   type: int
36470     #   register: 'eax'
36471     #
36472     # There's two primitives, as follows:
36473     #   - name: 'increment'
36474     #     out: int/reg
36475     #     value: 'ff 0/subop/increment'
36476     #   - name: 'increment'
36477     #     inout: int/mem
36478     #     value: 'ff 0/subop/increment'
36479     #
36480     # . prologue
36481     55/push-ebp
36482     89/<- %ebp 4/r32/esp
36483     # setup
36484     (clear-stream _test-output-stream)
36485     (clear-stream $_test-output-buffered-file->buffer)
36486 $test-emit-subx-stmt-select-primitive-2:initialize-type:
36487     # var type/ecx: (payload type-tree) = int
36488     68/push 0/imm32/right:null
36489     68/push 0/imm32/right:null
36490     68/push 0/imm32/left:unused
36491     68/push 1/imm32/value:int
36492     68/push 1/imm32/is-atom?:true
36493     68/push 0x11/imm32/alloc-id:fake:payload
36494     89/<- %ecx 4/r32/esp
36495 $test-emit-subx-stmt-select-primitive-2:initialize-var:
36496     # var var-foo/ecx: (payload var)
36497     68/push 0/imm32/register
36498     68/push 0/imm32/register
36499     68/push 0/imm32/no-stack-offset
36500     68/push 1/imm32/block-depth
36501     51/push-ecx
36502     68/push 0x11/imm32/alloc-id:fake
36503     68/push 0/imm32/name
36504     68/push 0/imm32/name
36505     68/push 0x11/imm32/alloc-id:fake:payload
36506     89/<- %ecx 4/r32/esp
36507 $test-emit-subx-stmt-select-primitive-2:initialize-var-name:
36508     # var-foo->name = "foo"
36509     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
36510     (copy-array Heap "foo" %eax)
36511 $test-emit-subx-stmt-select-primitive-2:initialize-var-register:
36512     # var-foo->register = "eax"
36513     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
36514     (copy-array Heap "eax" %eax)
36515 $test-emit-subx-stmt-select-primitive-2:initialize-stmt-var:
36516     # var operand/ebx: (payload stmt-var)
36517     68/push 0/imm32/is-deref:false
36518     68/push 0/imm32/next
36519     68/push 0/imm32/next
36520     51/push-ecx/var-foo
36521     68/push 0x11/imm32/alloc-id:fake
36522     68/push 0x11/imm32/alloc-id:fake:payload
36523     89/<- %ebx 4/r32/esp
36524 $test-emit-subx-stmt-select-primitive-2:initialize-stmt:
36525     # var stmt/esi: (addr statement)
36526     68/push 0/imm32/no-outputs
36527     68/push 0/imm32/no-outputs
36528     53/push-ebx/inouts
36529     68/push 0x11/imm32/alloc-id:fake
36530     68/push 0/imm32/operation
36531     68/push 0/imm32/operation
36532     68/push 1/imm32
36533     89/<- %esi 4/r32/esp
36534 $test-emit-subx-stmt-select-primitive-2:initialize-stmt-operation:
36535     # stmt->operation = "increment"
36536     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
36537     (copy-array Heap "increment" %eax)
36538 $test-emit-subx-stmt-select-primitive-2:initialize-formal-var:
36539     # var formal-var/ebx: (payload var)
36540     68/push 0/imm32/register
36541     68/push 0/imm32/register
36542     68/push 0/imm32/no-stack-offset
36543     68/push 1/imm32/block-depth
36544     ff 6/subop/push *(ecx+0x10)  # Var-type + payload alloc id + handle alloc id
36545     68/push 0x11/imm32/alloc-id:fake
36546     68/push 0/imm32/name
36547     68/push 0/imm32/name
36548     68/push 0x11/imm32/alloc-id:fake:payload
36549     89/<- %ebx 4/r32/esp
36550 $test-emit-subx-stmt-select-primitive-2:initialize-formal-var-name:
36551     # formal-var->name = "dummy"
36552     8d/copy-address *(ebx+4) 0/r32/eax  # Var-name + 4
36553     (copy-array Heap "dummy" %eax)
36554 $test-emit-subx-stmt-select-primitive-2:initialize-formal-register:
36555     # formal-var->register = "*"
36556     8d/copy-address *(ebx+0x1c) 0/r32/eax  # Var-register + 4
36557     (copy-array Heap "*" %eax)  # Any-register
36558 $test-emit-subx-stmt-select-primitive-2:initialize-var-list:
36559     # var formal-outputs/ebx: (payload list stmt-var)
36560     68/push 0/imm32/next
36561     68/push 0/imm32/next
36562     53/push-ebx/formal-var
36563     68/push 0x11/imm32/alloc-id:fake
36564     68/push 0x11/imm32/alloc-id:fake:payload
36565     89/<- %ebx 4/r32/esp
36566 $test-emit-subx-stmt-select-primitive-2:initialize-primitive2:
36567     # var primitive2/edi: (payload primitive)
36568     68/push 0/imm32/next
36569     68/push 0/imm32/next
36570     68/push 0/imm32/no-x32
36571     68/push 0/imm32/no-xm32
36572     68/push 0/imm32/no-disp32
36573     68/push 0/imm32/no-imm8
36574     68/push 0/imm32/no-imm32
36575     68/push 0/imm32/no-r32
36576     68/push 3/imm32/rm32-is-first-output
36577     68/push 0/imm32/subx-name
36578     68/push 0/imm32/subx-name
36579     53/push-ebx/outputs
36580     68/push 0x11/imm32/alloc-id:fake
36581     68/push 0/imm32/no-inouts
36582     68/push 0/imm32/no-inouts
36583     68/push 0/imm32/name
36584     68/push 0/imm32/name
36585     68/push 0x11/imm32/alloc-id:fake:payload
36586     89/<- %edi 4/r32/esp
36587 $test-emit-subx-stmt-select-primitive-2:initialize-primitive2-name:
36588     # primitives->name = "increment"
36589     8d/copy-address *(edi+4) 0/r32/eax  # Primitive-name + 4
36590     (copy-array Heap "increment" %eax)
36591 $test-emit-subx-stmt-select-primitive-2:initialize-primitive2-subx-name:
36592     # primitives->subx-name = "ff 0/subop/increment"
36593     8d/copy-address *(edi+0x1c) 0/r32/eax  # Primitive-subx-name + 4
36594     (copy-array Heap "ff 0/subop/increment" %eax)
36595 $test-emit-subx-stmt-select-primitive-2:initialize-primitive:
36596     # var primitives/ebx: (addr primitive)
36597     57/push-edi
36598     68/push 0x11/imm32/alloc-id:fake
36599     68/push 0/imm32/no-x32
36600     68/push 0/imm32/no-xm32
36601     68/push 0/imm32/no-disp32
36602     68/push 0/imm32/no-imm8
36603     68/push 0/imm32/no-imm32
36604     68/push 0/imm32/no-r32
36605     68/push 1/imm32/rm32-is-first-inout
36606     68/push 0/imm32/subx-name
36607     68/push 0/imm32/subx-name
36608     68/push 0/imm32/no-outputs
36609     68/push 0/imm32/no-outputs
36610     53/push-ebx/inouts  # hack: reuse stmt-var from call stmt as (list var) in function declaration
36611     68/push 0x11/imm32/alloc-id:fake
36612     68/push 0/imm32/name
36613     68/push 0/imm32/name
36614     89/<- %ebx 4/r32/esp
36615 $test-emit-subx-stmt-select-primitive-2:initialize-primitive-name:
36616     # primitives->name = "increment"
36617     (copy-array Heap "increment" %ebx)  # Primitive-name
36618 $test-emit-subx-stmt-select-primitive-2:initialize-primitive-subx-name:
36619     # primitives->subx-name = "ff 0/subop/increment"
36620     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
36621     (copy-array Heap "ff 0/subop/increment" %eax)
36622     # convert
36623     c7 0/subop/copy *Curr-block-depth 0/imm32
36624     (emit-subx-stmt _test-output-buffered-file %esi %ebx 0 Stderr 0)
36625     (flush _test-output-buffered-file)
36626 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
36632     # check output
36633     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-select-primitive-2")
36634     # . epilogue
36635     89/<- %esp 5/r32/ebp
36636     5d/pop-to-ebp
36637     c3/return
36638 
36639 test-increment-register:
36640     # Select the right register between overloads.
36641     #   foo <- increment
36642     # =>
36643     #   50/increment-eax
36644     #
36645     # There's a variable on the var stack as follows:
36646     #   name: 'foo'
36647     #   type: int
36648     #   register: 'eax'
36649     #
36650     # Primitives are the global definitions.
36651     #
36652     # . prologue
36653     55/push-ebp
36654     89/<- %ebp 4/r32/esp
36655     # setup
36656     (clear-stream _test-output-stream)
36657     (clear-stream $_test-output-buffered-file->buffer)
36658 $test-increment-register:initialize-type:
36659     # var type/ecx: (payload type-tree) = int
36660     68/push 0/imm32/right:null
36661     68/push 0/imm32/right:null
36662     68/push 0/imm32/left:unused
36663     68/push 1/imm32/value:int
36664     68/push 1/imm32/is-atom?:true
36665     68/push 0x11/imm32/alloc-id:fake:payload
36666     89/<- %ecx 4/r32/esp
36667 $test-increment-register:initialize-var:
36668     # var var-foo/ecx: (payload var)
36669     68/push 0/imm32/register
36670     68/push 0/imm32/register
36671     68/push 0/imm32/no-stack-offset
36672     68/push 1/imm32/block-depth
36673     51/push-ecx
36674     68/push 0x11/imm32/alloc-id:fake
36675     68/push 0/imm32/name
36676     68/push 0/imm32/name
36677     68/push 0x11/imm32/alloc-id:fake:payload
36678     89/<- %ecx 4/r32/esp
36679 $test-increment-register:initialize-var-name:
36680     # var-foo->name = "foo"
36681     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
36682     (copy-array Heap "foo" %eax)
36683 $test-increment-register:initialize-var-register:
36684     # var-foo->register = "eax"
36685     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
36686     (copy-array Heap "eax" %eax)
36687 $test-increment-register:initialize-stmt-var:
36688     # var operand/ebx: (payload stmt-var)
36689     68/push 0/imm32/is-deref:false
36690     68/push 0/imm32/next
36691     68/push 0/imm32/next
36692     51/push-ecx/var-foo
36693     68/push 0x11/imm32/alloc-id:fake
36694     68/push 0x11/imm32/alloc-id:fake:payload
36695     89/<- %ebx 4/r32/esp
36696 $test-increment-register:initialize-stmt:
36697     # var stmt/esi: (addr statement)
36698     53/push-ebx/outputs
36699     68/push 0x11/imm32/alloc-id:fake
36700     68/push 0/imm32/no-inouts
36701     68/push 0/imm32/no-inouts
36702     68/push 0/imm32/operation
36703     68/push 0/imm32/operation
36704     68/push 1/imm32
36705     89/<- %esi 4/r32/esp
36706 $test-increment-register:initialize-stmt-operation:
36707     # stmt->operation = "increment"
36708     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
36709     (copy-array Heap "increment" %eax)
36710     # convert
36711     c7 0/subop/copy *Curr-block-depth 0/imm32
36712     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
36713     (flush _test-output-buffered-file)
36714 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
36720     # check output
36721     (check-next-stream-line-equal _test-output-stream "40/increment-eax" "F - test-increment-register")
36722     # . epilogue
36723     89/<- %esp 5/r32/ebp
36724     5d/pop-to-ebp
36725     c3/return
36726 
36727 test-add-reg-to-reg:
36728     #   var1/reg <- add var2/reg
36729     # =>
36730     #   01/add-to %var1 var2
36731     #
36732     # . prologue
36733     55/push-ebp
36734     89/<- %ebp 4/r32/esp
36735     # setup
36736     (clear-stream _test-output-stream)
36737     (clear-stream $_test-output-buffered-file->buffer)
36738 $test-add-reg-to-reg:initialize-type:
36739     # var type/ecx: (payload type-tree) = int
36740     68/push 0/imm32/right:null
36741     68/push 0/imm32/right:null
36742     68/push 0/imm32/left:unused
36743     68/push 1/imm32/value:int
36744     68/push 1/imm32/is-atom?:true
36745     68/push 0x11/imm32/alloc-id:fake:payload
36746     89/<- %ecx 4/r32/esp
36747 $test-add-reg-to-reg:initialize-var1:
36748     # var var1/ecx: (payload var)
36749     68/push 0/imm32/register
36750     68/push 0/imm32/register
36751     68/push 0/imm32/no-stack-offset
36752     68/push 1/imm32/block-depth
36753     51/push-ecx
36754     68/push 0x11/imm32/alloc-id:fake
36755     68/push 0/imm32/name
36756     68/push 0/imm32/name
36757     68/push 0x11/imm32/alloc-id:fake:payload
36758     89/<- %ecx 4/r32/esp
36759 $test-add-reg-to-reg:initialize-var1-name:
36760     # var1->name = "var1"
36761     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
36762     (copy-array Heap "var1" %eax)
36763 $test-add-reg-to-reg:initialize-var1-register:
36764     # var1->register = "eax"
36765     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
36766     (copy-array Heap "eax" %eax)
36767 $test-add-reg-to-reg:initialize-var2:
36768     # var var2/edx: (payload var)
36769     68/push 0/imm32/register
36770     68/push 0/imm32/register
36771     68/push 0/imm32/no-stack-offset
36772     68/push 1/imm32/block-depth
36773     ff 6/subop/push *(ecx+0x10)
36774     68/push 0x11/imm32/alloc-id:fake
36775     68/push 0/imm32/name
36776     68/push 0/imm32/name
36777     68/push 0x11/imm32/alloc-id:fake:payload
36778     89/<- %edx 4/r32/esp
36779 $test-add-reg-to-reg:initialize-var2-name:
36780     # var2->name = "var2"
36781     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
36782     (copy-array Heap "var2" %eax)
36783 $test-add-reg-to-reg:initialize-var2-register:
36784     # var2->register = "ecx"
36785     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
36786     (copy-array Heap "ecx" %eax)
36787 $test-add-reg-to-reg:initialize-inouts:
36788     # var inouts/esi: (payload stmt-var) = [var2]
36789     68/push 0/imm32/is-deref:false
36790     68/push 0/imm32/next
36791     68/push 0/imm32/next
36792     52/push-edx/var2
36793     68/push 0x11/imm32/alloc-id:fake
36794     68/push 0x11/imm32/alloc-id:fake:payload
36795     89/<- %esi 4/r32/esp
36796 $test-add-reg-to-reg:initialize-outputs:
36797     # var outputs/edi: (payload stmt-var) = [var1]
36798     68/push 0/imm32/is-deref:false
36799     68/push 0/imm32/next
36800     68/push 0/imm32/next
36801     51/push-ecx/var1
36802     68/push 0x11/imm32/alloc-id:fake
36803     68/push 0x11/imm32/alloc-id:fake:payload
36804     89/<- %edi 4/r32/esp
36805 $test-add-reg-to-reg:initialize-stmt:
36806     # var stmt/esi: (addr statement)
36807     68/push 0/imm32/next
36808     68/push 0/imm32/next
36809     57/push-edi/outputs
36810     68/push 0x11/imm32/alloc-id:fake
36811     56/push-esi/inouts
36812     68/push 0x11/imm32/alloc-id:fake
36813     68/push 0/imm32/operation
36814     68/push 0/imm32/operation
36815     68/push 1/imm32/tag:stmt1
36816     89/<- %esi 4/r32/esp
36817 $test-add-reg-to-reg:initialize-stmt-operation:
36818     # stmt->operation = "add"
36819     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
36820     (copy-array Heap "add" %eax)
36821     # convert
36822     c7 0/subop/copy *Curr-block-depth 0/imm32
36823     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
36824     (flush _test-output-buffered-file)
36825 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
36831     # check output
36832     (check-next-stream-line-equal _test-output-stream "01/add-to %eax 0x00000001/r32" "F - test-add-reg-to-reg")
36833     # . epilogue
36834     89/<- %esp 5/r32/ebp
36835     5d/pop-to-ebp
36836     c3/return
36837 
36838 test-add-reg-to-mem:
36839     #   add-to var1 var2/reg
36840     # =>
36841     #   01/add-to *(ebp+__) var2
36842     #
36843     # . prologue
36844     55/push-ebp
36845     89/<- %ebp 4/r32/esp
36846     # setup
36847     (clear-stream _test-output-stream)
36848     (clear-stream $_test-output-buffered-file->buffer)
36849 $test-add-reg-to-mem:initialize-type:
36850     # var type/ecx: (payload type-tree) = int
36851     68/push 0/imm32/right:null
36852     68/push 0/imm32/right:null
36853     68/push 0/imm32/left:unused
36854     68/push 1/imm32/value:int
36855     68/push 1/imm32/is-atom?:true
36856     68/push 0x11/imm32/alloc-id:fake:payload
36857     89/<- %ecx 4/r32/esp
36858 $test-add-reg-to-mem:initialize-var1:
36859     # var var1/ecx: (payload var)
36860     68/push 0/imm32/register
36861     68/push 0/imm32/register
36862     68/push 8/imm32/stack-offset
36863     68/push 1/imm32/block-depth
36864     51/push-ecx
36865     68/push 0x11/imm32/alloc-id:fake
36866     68/push 0/imm32/name
36867     68/push 0/imm32/name
36868     68/push 0x11/imm32/alloc-id:fake:payload
36869     89/<- %ecx 4/r32/esp
36870 $test-add-reg-to-mem:initialize-var1-name:
36871     # var1->name = "var1"
36872     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
36873     (copy-array Heap "var1" %eax)
36874 $test-add-reg-to-mem:initialize-var2:
36875     # var var2/edx: (payload var)
36876     68/push 0/imm32/register
36877     68/push 0/imm32/register
36878     68/push 0/imm32/no-stack-offset
36879     68/push 1/imm32/block-depth
36880     ff 6/subop/push *(ecx+0x10)
36881     68/push 0x11/imm32/alloc-id:fake
36882     68/push 0/imm32/name
36883     68/push 0/imm32/name
36884     68/push 0x11/imm32/alloc-id:fake:payload
36885     89/<- %edx 4/r32/esp
36886 $test-add-reg-to-mem:initialize-var2-name:
36887     # var2->name = "var2"
36888     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
36889     (copy-array Heap "var2" %eax)
36890 $test-add-reg-to-mem:initialize-var2-register:
36891     # var2->register = "ecx"
36892     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
36893     (copy-array Heap "ecx" %eax)
36894 $test-add-reg-to-mem:initialize-inouts:
36895     # var inouts/esi: (payload stmt-var) = [var2]
36896     68/push 0/imm32/is-deref:false
36897     68/push 0/imm32/next
36898     68/push 0/imm32/next
36899     52/push-edx/var2
36900     68/push 0x11/imm32/alloc-id:fake
36901     68/push 0x11/imm32/alloc-id:fake:payload
36902     89/<- %esi 4/r32/esp
36903     # inouts = [var1, var2]
36904     68/push 0/imm32/is-deref:false
36905     56/push-esi/next
36906     68/push 0x11/imm32/alloc-id:fake
36907     51/push-ecx/var1
36908     68/push 0x11/imm32/alloc-id:fake
36909     68/push 0x11/imm32/alloc-id:fake:payload
36910     89/<- %esi 4/r32/esp
36911 $test-add-reg-to-mem:initialize-stmt:
36912     # var stmt/esi: (addr statement)
36913     68/push 0/imm32/next
36914     68/push 0/imm32/next
36915     68/push 0/imm32/outputs
36916     68/push 0/imm32/outputs
36917     56/push-esi/inouts
36918     68/push 0x11/imm32/alloc-id:fake
36919     68/push 0/imm32/operation
36920     68/push 0/imm32/operation
36921     68/push 1/imm32/tag:stmt1
36922     89/<- %esi 4/r32/esp
36923 $test-add-reg-to-mem:initialize-stmt-operation:
36924     # stmt->operation = "add-to"
36925     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
36926     (copy-array Heap "add-to" %eax)
36927     # convert
36928     c7 0/subop/copy *Curr-block-depth 0/imm32
36929     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
36930     (flush _test-output-buffered-file)
36931 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
36937     # check output
36938     (check-next-stream-line-equal _test-output-stream "01/add-to *(ebp+0x00000008) 0x00000001/r32" "F - test-add-reg-to-mem")
36939     # . epilogue
36940     89/<- %esp 5/r32/ebp
36941     5d/pop-to-ebp
36942     c3/return
36943 
36944 test-add-mem-to-reg:
36945     #   var1/reg <- add var2
36946     # =>
36947     #   03/add *(ebp+__) var1
36948     #
36949     # . prologue
36950     55/push-ebp
36951     89/<- %ebp 4/r32/esp
36952     # setup
36953     (clear-stream _test-output-stream)
36954     (clear-stream $_test-output-buffered-file->buffer)
36955 $test-add-mem-to-reg:initialize-type:
36956     # var type/ecx: (payload type-tree) = int
36957     68/push 0/imm32/right:null
36958     68/push 0/imm32/right:null
36959     68/push 0/imm32/left:unused
36960     68/push 1/imm32/value:int
36961     68/push 1/imm32/is-atom?:true
36962     68/push 0x11/imm32/alloc-id:fake:payload
36963     89/<- %ecx 4/r32/esp
36964 $test-add-mem-to-reg:initialize-var:
36965     # var var1/ecx: (payload var)
36966     68/push 0/imm32/register
36967     68/push 0/imm32/register
36968     68/push 0/imm32/no-stack-offset
36969     68/push 1/imm32/block-depth
36970     51/push-ecx
36971     68/push 0x11/imm32/alloc-id:fake
36972     68/push 0/imm32/name
36973     68/push 0/imm32/name
36974     68/push 0x11/imm32/alloc-id:fake:payload
36975     89/<- %ecx 4/r32/esp
36976 $test-add-mem-to-reg:initialize-var-name:
36977     # var1->name = "foo"
36978     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
36979     (copy-array Heap "var1" %eax)
36980 $test-add-mem-to-reg:initialize-var-register:
36981     # var1->register = "eax"
36982     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
36983     (copy-array Heap "eax" %eax)
36984 $test-add-mem-to-reg:initialize-var2:
36985     # var var2/edx: (payload var)
36986     68/push 0/imm32/register
36987     68/push 0/imm32/register
36988     68/push 8/imm32/stack-offset
36989     68/push 1/imm32/block-depth
36990     ff 6/subop/push *(ecx+0x10)
36991     68/push 0x11/imm32/alloc-id:fake
36992     68/push 0/imm32/name
36993     68/push 0/imm32/name
36994     68/push 0x11/imm32/alloc-id:fake:payload
36995     89/<- %edx 4/r32/esp
36996 $test-add-mem-to-reg:initialize-var2-name:
36997     # var2->name = "var2"
36998     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
36999     (copy-array Heap "var2" %eax)
37000 $test-add-mem-to-reg:initialize-inouts:
37001     # var inouts/esi: (payload stmt-var) = [var2]
37002     68/push 0/imm32/is-deref:false
37003     68/push 0/imm32/next
37004     68/push 0/imm32/next
37005     52/push-edx/var2
37006     68/push 0x11/imm32/alloc-id:fake
37007     68/push 0x11/imm32/alloc-id:fake:payload
37008     89/<- %esi 4/r32/esp
37009 $test-add-mem-to-reg:initialize-outputs:
37010     # var outputs/edi: (payload stmt-var) = [var1]
37011     68/push 0/imm32/is-deref:false
37012     68/push 0/imm32/next
37013     68/push 0/imm32/next
37014     51/push-ecx/var1
37015     68/push 0x11/imm32/alloc-id:fake
37016     68/push 0x11/imm32/alloc-id:fake:payload
37017     89/<- %edi 4/r32/esp
37018 $test-add-mem-to-reg:initialize-stmt:
37019     # var stmt/esi: (addr statement)
37020     68/push 0/imm32/next
37021     68/push 0/imm32/next
37022     57/push-edi/outputs
37023     68/push 0x11/imm32/alloc-id:fake
37024     56/push-esi/inouts
37025     68/push 0x11/imm32/alloc-id:fake
37026     68/push 0/imm32/operation
37027     68/push 0/imm32/operation
37028     68/push 1/imm32/tag:stmt1
37029     89/<- %esi 4/r32/esp
37030 $test-add-mem-to-reg:initialize-stmt-operation:
37031     # stmt->operation = "add"
37032     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
37033     (copy-array Heap "add" %eax)
37034     # convert
37035     c7 0/subop/copy *Curr-block-depth 0/imm32
37036     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
37037     (flush _test-output-buffered-file)
37038 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
37044     # check output
37045     (check-next-stream-line-equal _test-output-stream "03/add *(ebp+0x00000008) 0x00000000/r32" "F - test-add-mem-to-reg")
37046     # . epilogue
37047     89/<- %esp 5/r32/ebp
37048     5d/pop-to-ebp
37049     c3/return
37050 
37051 test-add-literal-to-eax:
37052     #   var1/eax <- add 0x34
37053     # =>
37054     #   05/add-to-eax 0x34/imm32
37055     #
37056     # . prologue
37057     55/push-ebp
37058     89/<- %ebp 4/r32/esp
37059     # setup
37060     (clear-stream _test-output-stream)
37061     (clear-stream $_test-output-buffered-file->buffer)
37062 $test-add-literal-to-eax:initialize-var-type:
37063     # var type/ecx: (payload type-tree) = int
37064     68/push 0/imm32/right:null
37065     68/push 0/imm32/right:null
37066     68/push 0/imm32/left:unused
37067     68/push 1/imm32/value:int
37068     68/push 1/imm32/is-atom?:true
37069     68/push 0x11/imm32/alloc-id:fake:payload
37070     89/<- %ecx 4/r32/esp
37071 $test-add-literal-to-eax:initialize-var:
37072     # var v/ecx: (payload var)
37073     68/push 0/imm32/register
37074     68/push 0/imm32/register
37075     68/push 0/imm32/no-stack-offset
37076     68/push 1/imm32/block-depth
37077     51/push-ecx
37078     68/push 0x11/imm32/alloc-id:fake
37079     68/push 0/imm32/name
37080     68/push 0/imm32/name
37081     68/push 0x11/imm32/alloc-id:fake:payload
37082     89/<- %ecx 4/r32/esp
37083 $test-add-literal-to-eax:initialize-var-name:
37084     # v->name = "v"
37085     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
37086     (copy-array Heap "v" %eax)
37087 $test-add-literal-to-eax:initialize-var-register:
37088     # v->register = "eax"
37089     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
37090     (copy-array Heap "eax" %eax)
37091 $test-add-literal-to-eax:initialize-literal-type:
37092     # var type/edx: (payload type-tree) = literal
37093     68/push 0/imm32/right:null
37094     68/push 0/imm32/right:null
37095     68/push 0/imm32/left:unused
37096     68/push 0/imm32/value:literal
37097     68/push 1/imm32/is-atom?:true
37098     68/push 0x11/imm32/alloc-id:fake:payload
37099     89/<- %edx 4/r32/esp
37100 $test-add-literal-to-eax:initialize-literal:
37101     # var l/edx: (payload var)
37102     68/push 0/imm32/register
37103     68/push 0/imm32/register
37104     68/push 0/imm32/no-stack-offset
37105     68/push 1/imm32/block-depth
37106     52/push-edx
37107     68/push 0x11/imm32/alloc-id:fake
37108     68/push 0/imm32/name
37109     68/push 0/imm32/name
37110     68/push 0x11/imm32/alloc-id:fake:payload
37111     89/<- %edx 4/r32/esp
37112 $test-add-literal-to-eax:initialize-literal-value:
37113     # l->name = "0x34"
37114     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
37115     (copy-array Heap "0x34" %eax)
37116 $test-add-literal-to-eax:initialize-inouts:
37117     # var inouts/esi: (payload stmt-var) = [l]
37118     68/push 0/imm32/is-deref:false
37119     68/push 0/imm32/next
37120     68/push 0/imm32/next
37121     52/push-edx/l
37122     68/push 0x11/imm32/alloc-id:fake
37123     68/push 0x11/imm32/alloc-id:fake:payload
37124     89/<- %esi 4/r32/esp
37125 $test-add-literal-to-eax:initialize-outputs:
37126     # var outputs/edi: (payload stmt-var) = [v]
37127     68/push 0/imm32/is-deref:false
37128     68/push 0/imm32/next
37129     68/push 0/imm32/next
37130     51/push-ecx/v
37131     68/push 0x11/imm32/alloc-id:fake
37132     68/push 0x11/imm32/alloc-id:fake:payload
37133     89/<- %edi 4/r32/esp
37134 $test-add-literal-to-eax:initialize-stmt:
37135     # var stmt/esi: (addr statement)
37136     68/push 0/imm32/next
37137     68/push 0/imm32/next
37138     57/push-edi/outputs
37139     68/push 0x11/imm32/alloc-id:fake
37140     56/push-esi/inouts
37141     68/push 0x11/imm32/alloc-id:fake
37142     68/push 0/imm32/operation
37143     68/push 0/imm32/operation
37144     68/push 1/imm32/tag:stmt1
37145     89/<- %esi 4/r32/esp
37146 $test-add-literal-to-eax:initialize-stmt-operation:
37147     # stmt->operation = "add"
37148     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
37149     (copy-array Heap "add" %eax)
37150     # convert
37151     c7 0/subop/copy *Curr-block-depth 0/imm32
37152     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
37153     (flush _test-output-buffered-file)
37154 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
37160     # check output
37161     (check-next-stream-line-equal _test-output-stream "05/add-to-eax 0x34/imm32" "F - test-add-literal-to-eax")
37162     # . epilogue
37163     89/<- %esp 5/r32/ebp
37164     5d/pop-to-ebp
37165     c3/return
37166 
37167 test-add-literal-to-reg:
37168     #   var1/ecx <- add 0x34
37169     # =>
37170     #   81 0/subop/add %ecx 0x34/imm32
37171     #
37172     # . prologue
37173     55/push-ebp
37174     89/<- %ebp 4/r32/esp
37175     # setup
37176     (clear-stream _test-output-stream)
37177     (clear-stream $_test-output-buffered-file->buffer)
37178 $test-add-literal-to-reg:initialize-var-type:
37179     # var type/ecx: (payload type-tree) = int
37180     68/push 0/imm32/right:null
37181     68/push 0/imm32/right:null
37182     68/push 0/imm32/left:unused
37183     68/push 1/imm32/value:int
37184     68/push 1/imm32/is-atom?:true
37185     68/push 0x11/imm32/alloc-id:fake:payload
37186     89/<- %ecx 4/r32/esp
37187 $test-add-literal-to-reg:initialize-var:
37188     # var v/ecx: (payload var)
37189     68/push 0/imm32/register
37190     68/push 0/imm32/register
37191     68/push 0/imm32/no-stack-offset
37192     68/push 1/imm32/block-depth
37193     51/push-ecx
37194     68/push 0x11/imm32/alloc-id:fake
37195     68/push 0/imm32/name
37196     68/push 0/imm32/name
37197     68/push 0x11/imm32/alloc-id:fake:payload
37198     89/<- %ecx 4/r32/esp
37199 $test-add-literal-to-reg:initialize-var-name:
37200     # v->name = "v"
37201     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
37202     (copy-array Heap "v" %eax)
37203 $test-add-literal-to-reg:initialize-var-register:
37204     # v->register = "ecx"
37205     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
37206     (copy-array Heap "ecx" %eax)
37207 $test-add-literal-to-reg:initialize-literal-type:
37208     # var type/edx: (payload type-tree) = literal
37209     68/push 0/imm32/right:null
37210     68/push 0/imm32/right:null
37211     68/push 0/imm32/left:unused
37212     68/push 0/imm32/value:literal
37213     68/push 1/imm32/is-atom?:true
37214     68/push 0x11/imm32/alloc-id:fake:payload
37215     89/<- %edx 4/r32/esp
37216 $test-add-literal-to-reg:initialize-literal:
37217     # var l/edx: (payload var)
37218     68/push 0/imm32/register
37219     68/push 0/imm32/register
37220     68/push 0/imm32/no-stack-offset
37221     68/push 1/imm32/block-depth
37222     52/push-edx
37223     68/push 0x11/imm32/alloc-id:fake
37224     68/push 0/imm32/name
37225     68/push 0/imm32/name
37226     68/push 0x11/imm32/alloc-id:fake:payload
37227     89/<- %edx 4/r32/esp
37228 $test-add-literal-to-reg:initialize-literal-value:
37229     # l->name = "0x34"
37230     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
37231     (copy-array Heap "0x34" %eax)
37232 $test-add-literal-to-reg:initialize-inouts:
37233     # var inouts/esi: (payload stmt-var) = [l]
37234     68/push 0/imm32/is-deref:false
37235     68/push 0/imm32/next
37236     68/push 0/imm32/next
37237     52/push-edx/l
37238     68/push 0x11/imm32/alloc-id:fake
37239     68/push 0x11/imm32/alloc-id:fake:payload
37240     89/<- %esi 4/r32/esp
37241 $test-add-literal-to-reg:initialize-outputs:
37242     # var outputs/edi: (payload stmt-var) = [v]
37243     68/push 0/imm32/is-deref:false
37244     68/push 0/imm32/next
37245     68/push 0/imm32/next
37246     51/push-ecx/v
37247     68/push 0x11/imm32/alloc-id:fake
37248     68/push 0x11/imm32/alloc-id:fake:payload
37249     89/<- %edi 4/r32/esp
37250 $test-add-literal-to-reg:initialize-stmt:
37251     # var stmt/esi: (addr statement)
37252     68/push 0/imm32/next
37253     68/push 0/imm32/next
37254     57/push-edi/outputs
37255     68/push 0x11/imm32/alloc-id:fake
37256     56/push-esi/inouts
37257     68/push 0x11/imm32/alloc-id:fake
37258     68/push 0/imm32/operation
37259     68/push 0/imm32/operation
37260     68/push 1/imm32/tag:stmt1
37261     89/<- %esi 4/r32/esp
37262 $test-add-literal-to-reg:initialize-stmt-operation:
37263     # stmt->operation = "add"
37264     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
37265     (copy-array Heap "add" %eax)
37266     # convert
37267     c7 0/subop/copy *Curr-block-depth 0/imm32
37268     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
37269     (flush _test-output-buffered-file)
37270 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
37276     # check output
37277     (check-next-stream-line-equal _test-output-stream "81 0/subop/add %ecx 0x34/imm32" "F - test-add-literal-to-reg")
37278     # . epilogue
37279     89/<- %esp 5/r32/ebp
37280     5d/pop-to-ebp
37281     c3/return
37282 
37283 test-add-literal-to-mem:
37284     #   add-to var1, 0x34
37285     # =>
37286     #   81 0/subop/add %eax 0x34/imm32
37287     #
37288     # . prologue
37289     55/push-ebp
37290     89/<- %ebp 4/r32/esp
37291     # setup
37292     (clear-stream _test-output-stream)
37293     (clear-stream $_test-output-buffered-file->buffer)
37294 $test-add-literal-to-mem:initialize-type:
37295     # var type/ecx: (payload type-tree) = int
37296     68/push 0/imm32/right:null
37297     68/push 0/imm32/right:null
37298     68/push 0/imm32/left:unused
37299     68/push 1/imm32/value:int
37300     68/push 1/imm32/is-atom?:true
37301     68/push 0x11/imm32/alloc-id:fake:payload
37302     89/<- %ecx 4/r32/esp
37303 $test-add-literal-to-mem:initialize-var1:
37304     # var var1/ecx: (payload var)
37305     68/push 0/imm32/register
37306     68/push 0/imm32/register
37307     68/push 8/imm32/stack-offset
37308     68/push 1/imm32/block-depth
37309     51/push-ecx
37310     68/push 0x11/imm32/alloc-id:fake
37311     68/push 0/imm32/name
37312     68/push 0/imm32/name
37313     68/push 0x11/imm32/alloc-id:fake:payload
37314     89/<- %ecx 4/r32/esp
37315 $test-add-literal-to-mem:initialize-var1-name:
37316     # var1->name = "var1"
37317     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
37318     (copy-array Heap "var1" %eax)
37319 $test-add-literal-to-mem:initialize-literal-type:
37320     # var type/edx: (payload type-tree) = literal
37321     68/push 0/imm32/right:null
37322     68/push 0/imm32/right:null
37323     68/push 0/imm32/left:unused
37324     68/push 0/imm32/value:literal
37325     68/push 1/imm32/is-atom?:true
37326     68/push 0x11/imm32/alloc-id:fake:payload
37327     89/<- %edx 4/r32/esp
37328 $test-add-literal-to-mem:initialize-literal:
37329     # var l/edx: (payload var)
37330     68/push 0/imm32/register
37331     68/push 0/imm32/register
37332     68/push 0/imm32/no-stack-offset
37333     68/push 1/imm32/block-depth
37334     52/push-edx
37335     68/push 0x11/imm32/alloc-id:fake
37336     68/push 0/imm32/name
37337     68/push 0/imm32/name
37338     68/push 0x11/imm32/alloc-id:fake:payload
37339     89/<- %edx 4/r32/esp
37340 $test-add-literal-to-mem:initialize-literal-value:
37341     # l->name = "0x34"
37342     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
37343     (copy-array Heap "0x34" %eax)
37344 $test-add-literal-to-mem:initialize-inouts:
37345     # var inouts/esi: (payload stmt-var) = [l]
37346     68/push 0/imm32/is-deref:false
37347     68/push 0/imm32/next
37348     68/push 0/imm32/next
37349     52/push-edx/l
37350     68/push 0x11/imm32/alloc-id:fake
37351     68/push 0x11/imm32/alloc-id:fake:payload
37352     89/<- %esi 4/r32/esp
37353     # var inouts = (handle stmt-var) = [var1, var2]
37354     68/push 0/imm32/is-deref:false
37355     56/push-esi/next
37356     68/push 0x11/imm32/alloc-id:fake
37357     51/push-ecx/var1
37358     68/push 0x11/imm32/alloc-id:fake
37359     68/push 0x11/imm32/alloc-id:fake:payload
37360     89/<- %esi 4/r32/esp
37361 $test-add-literal-to-mem:initialize-stmt:
37362     # var stmt/esi: (addr statement)
37363     68/push 0/imm32/next
37364     68/push 0/imm32/next
37365     68/push 0/imm32/outputs
37366     68/push 0/imm32/outputs
37367     56/push-esi/inouts
37368     68/push 0x11/imm32/alloc-id:fake
37369     68/push 0/imm32/operation
37370     68/push 0/imm32/operation
37371     68/push 1/imm32/tag:stmt1
37372     89/<- %esi 4/r32/esp
37373 $test-add-literal-to-mem:initialize-stmt-operation:
37374     # stmt->operation = "add-to"
37375     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
37376     (copy-array Heap "add-to" %eax)
37377     # convert
37378     c7 0/subop/copy *Curr-block-depth 0/imm32
37379     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
37380     (flush _test-output-buffered-file)
37381 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
37387     # check output
37388     (check-next-stream-line-equal _test-output-stream "81 0/subop/add *(ebp+0x00000008) 0x34/imm32" "F - test-add-literal-to-mem")
37389     # . epilogue
37390     89/<- %esp 5/r32/ebp
37391     5d/pop-to-ebp
37392     c3/return
37393 
37394 test-shift-reg-by-literal:
37395     #   var1/ecx <- shift-left 2
37396     # =>
37397     #   c1/shift 4/subop/left %ecx 2/imm8
37398     #
37399     # . prologue
37400     55/push-ebp
37401     89/<- %ebp 4/r32/esp
37402     # setup
37403     (clear-stream _test-output-stream)
37404     (clear-stream $_test-output-buffered-file->buffer)
37405 $test-shift-reg-by-literal:initialize-var-type:
37406     # var type/ecx: (payload type-tree) = int
37407     68/push 0/imm32/right:null
37408     68/push 0/imm32/right:null
37409     68/push 0/imm32/left:unused
37410     68/push 1/imm32/value:int
37411     68/push 1/imm32/is-atom?:true
37412     68/push 0x11/imm32/alloc-id:fake:payload
37413     89/<- %ecx 4/r32/esp
37414 $test-shift-reg-by-literal:initialize-var:
37415     # var v/ecx: (payload var)
37416     68/push 0/imm32/register
37417     68/push 0/imm32/register
37418     68/push 0/imm32/no-stack-offset
37419     68/push 1/imm32/block-depth
37420     51/push-ecx
37421     68/push 0x11/imm32/alloc-id:fake
37422     68/push 0/imm32/name
37423     68/push 0/imm32/name
37424     68/push 0x11/imm32/alloc-id:fake:payload
37425     89/<- %ecx 4/r32/esp
37426 $test-shift-reg-by-literal:initialize-var-name:
37427     # v->name = "v"
37428     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
37429     (copy-array Heap "v" %eax)
37430 $test-shift-reg-by-literal:initialize-var-register:
37431     # v->register = "ecx"
37432     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
37433     (copy-array Heap "ecx" %eax)
37434 $test-shift-reg-by-literal:initialize-literal-type:
37435     # var type/edx: (payload type-tree) = literal
37436     68/push 0/imm32/right:null
37437     68/push 0/imm32/right:null
37438     68/push 0/imm32/left:unused
37439     68/push 0/imm32/value:literal
37440     68/push 1/imm32/is-atom?:true
37441     68/push 0x11/imm32/alloc-id:fake:payload
37442     89/<- %edx 4/r32/esp
37443 $test-shift-reg-by-literal:initialize-literal:
37444     # var l/edx: (payload var)
37445     68/push 0/imm32/register
37446     68/push 0/imm32/register
37447     68/push 0/imm32/no-stack-offset
37448     68/push 1/imm32/block-depth
37449     52/push-edx
37450     68/push 0x11/imm32/alloc-id:fake
37451     68/push 0/imm32/name
37452     68/push 0/imm32/name
37453     68/push 0x11/imm32/alloc-id:fake:payload
37454     89/<- %edx 4/r32/esp
37455 $test-shift-reg-by-literal:initialize-literal-value:
37456     # l->name = "2"
37457     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
37458     (copy-array Heap "2" %eax)
37459 $test-shift-reg-by-literal:initialize-inouts:
37460     # var inouts/esi: (payload stmt-var) = [l]
37461     68/push 0/imm32/is-deref:false
37462     68/push 0/imm32/next
37463     68/push 0/imm32/next
37464     52/push-edx/l
37465     68/push 0x11/imm32/alloc-id:fake
37466     68/push 0x11/imm32/alloc-id:fake:payload
37467     89/<- %esi 4/r32/esp
37468 $test-shift-reg-by-literal:initialize-outputs:
37469     # var outputs/edi: (payload stmt-var) = [v]
37470     68/push 0/imm32/is-deref:false
37471     68/push 0/imm32/next
37472     68/push 0/imm32/next
37473     51/push-ecx/v
37474     68/push 0x11/imm32/alloc-id:fake
37475     68/push 0x11/imm32/alloc-id:fake:payload
37476     89/<- %edi 4/r32/esp
37477 $test-shift-reg-by-literal:initialize-stmt:
37478     # var stmt/esi: (addr statement)
37479     68/push 0/imm32/next
37480     68/push 0/imm32/next
37481     57/push-edi/outputs
37482     68/push 0x11/imm32/alloc-id:fake
37483     56/push-esi/inouts
37484     68/push 0x11/imm32/alloc-id:fake
37485     68/push 0/imm32/operation
37486     68/push 0/imm32/operation
37487     68/push 1/imm32/tag:stmt1
37488     89/<- %esi 4/r32/esp
37489 $test-shift-reg-by-literal:initialize-stmt-operation:
37490     # stmt->operation = "shift-left"
37491     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
37492     (copy-array Heap "shift-left" %eax)
37493     # convert
37494     c7 0/subop/copy *Curr-block-depth 0/imm32
37495     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
37496     (flush _test-output-buffered-file)
37497 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
37503     # check output
37504     (check-next-stream-line-equal _test-output-stream "c1/shift 4/subop/left %ecx 2/imm8" "F - test-shift-reg-by-literal")
37505     # . epilogue
37506     89/<- %esp 5/r32/ebp
37507     5d/pop-to-ebp
37508     c3/return
37509 
37510 test-shift-mem-by-literal:
37511     #   shift-left var 3
37512     # =>
37513     #   c1/shift 4/subop/left *(ebp+8) 3/imm8
37514     #
37515     # . prologue
37516     55/push-ebp
37517     89/<- %ebp 4/r32/esp
37518     # setup
37519     (clear-stream _test-output-stream)
37520     (clear-stream $_test-output-buffered-file->buffer)
37521 $test-shift-mem-by-literal:initialize-type:
37522     # var type/ecx: (payload type-tree) = int
37523     68/push 0/imm32/right:null
37524     68/push 0/imm32/right:null
37525     68/push 0/imm32/left:unused
37526     68/push 1/imm32/value:int
37527     68/push 1/imm32/is-atom?:true
37528     68/push 0x11/imm32/alloc-id:fake:payload
37529     89/<- %ecx 4/r32/esp
37530 $test-shift-mem-by-literal:initialize-var1:
37531     # var var1/ecx: (payload var)
37532     68/push 0/imm32/register
37533     68/push 0/imm32/register
37534     68/push 8/imm32/stack-offset
37535     68/push 1/imm32/block-depth
37536     51/push-ecx
37537     68/push 0x11/imm32/alloc-id:fake
37538     68/push 0/imm32/name
37539     68/push 0/imm32/name
37540     68/push 0x11/imm32/alloc-id:fake:payload
37541     89/<- %ecx 4/r32/esp
37542 $test-shift-mem-by-literal:initialize-var1-name:
37543     # var1->name = "var1"
37544     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
37545     (copy-array Heap "var1" %eax)
37546 $test-shift-mem-by-literal:initialize-literal-type:
37547     # var type/edx: (payload type-tree) = literal
37548     68/push 0/imm32/right:null
37549     68/push 0/imm32/right:null
37550     68/push 0/imm32/left:unused
37551     68/push 0/imm32/value:literal
37552     68/push 1/imm32/is-atom?:true
37553     68/push 0x11/imm32/alloc-id:fake:payload
37554     89/<- %edx 4/r32/esp
37555 $test-shift-mem-by-literal:initialize-literal:
37556     # var l/edx: (payload var)
37557     68/push 0/imm32/register
37558     68/push 0/imm32/register
37559     68/push 0/imm32/no-stack-offset
37560     68/push 1/imm32/block-depth
37561     52/push-edx
37562     68/push 0x11/imm32/alloc-id:fake
37563     68/push 0/imm32/name
37564     68/push 0/imm32/name
37565     68/push 0x11/imm32/alloc-id:fake:payload
37566     89/<- %edx 4/r32/esp
37567 $test-shift-mem-by-literal:initialize-literal-value:
37568     # l->name = "3"
37569     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
37570     (copy-array Heap "3" %eax)
37571 $test-shift-mem-by-literal:initialize-inouts:
37572     # var inouts/esi: (payload stmt-var) = [l]
37573     68/push 0/imm32/is-deref:false
37574     68/push 0/imm32/next
37575     68/push 0/imm32/next
37576     52/push-edx/l
37577     68/push 0x11/imm32/alloc-id:fake
37578     68/push 0x11/imm32/alloc-id:fake:payload
37579     89/<- %esi 4/r32/esp
37580     # var inouts = (handle stmt-var) = [var1, var2]
37581     68/push 0/imm32/is-deref:false
37582     56/push-esi/next
37583     68/push 0x11/imm32/alloc-id:fake
37584     51/push-ecx/var1
37585     68/push 0x11/imm32/alloc-id:fake
37586     68/push 0x11/imm32/alloc-id:fake:payload
37587     89/<- %esi 4/r32/esp
37588 $test-shift-mem-by-literal:initialize-stmt:
37589     # var stmt/esi: (addr statement)
37590     68/push 0/imm32/next
37591     68/push 0/imm32/next
37592     68/push 0/imm32/outputs
37593     68/push 0/imm32/outputs
37594     56/push-esi/inouts
37595     68/push 0x11/imm32/alloc-id:fake
37596     68/push 0/imm32/operation
37597     68/push 0/imm32/operation
37598     68/push 1/imm32/tag:stmt1
37599     89/<- %esi 4/r32/esp
37600 $test-shift-mem-by-literal:initialize-stmt-operation:
37601     # stmt->operation = "shift-left"
37602     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
37603     (copy-array Heap "shift-left" %eax)
37604     # convert
37605     c7 0/subop/copy *Curr-block-depth 0/imm32
37606     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
37607     (flush _test-output-buffered-file)
37608 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
37614     # check output
37615     (check-next-stream-line-equal _test-output-stream "c1/shift 4/subop/left *(ebp+0x00000008) 3/imm8" "F - test-shift-mem-by-literal")
37616     # . epilogue
37617     89/<- %esp 5/r32/ebp
37618     5d/pop-to-ebp
37619     c3/return
37620 
37621 test-compare-reg-with-reg:
37622     #   compare var1/ecx, var2/eax
37623     # =>
37624     #   39/compare %ecx 0/r32/eax
37625     #
37626     # . prologue
37627     55/push-ebp
37628     89/<- %ebp 4/r32/esp
37629     # setup
37630     (clear-stream _test-output-stream)
37631     (clear-stream $_test-output-buffered-file->buffer)
37632 $test-compare-reg-with-reg:initialize-type:
37633     # var type/ecx: (payload type-tree) = int
37634     68/push 0/imm32/right:null
37635     68/push 0/imm32/right:null
37636     68/push 0/imm32/left:unused
37637     68/push 1/imm32/value:int
37638     68/push 1/imm32/is-atom?:true
37639     68/push 0x11/imm32/alloc-id:fake:payload
37640     89/<- %ecx 4/r32/esp
37641 $test-compare-reg-with-reg:initialize-var1:
37642     # var var1/ecx: (payload var)
37643     68/push 0/imm32/register
37644     68/push 0/imm32/register
37645     68/push 0/imm32/no-stack-offset
37646     68/push 1/imm32/block-depth
37647     51/push-ecx
37648     68/push 0x11/imm32/alloc-id:fake
37649     68/push 0/imm32/name
37650     68/push 0/imm32/name
37651     68/push 0x11/imm32/alloc-id:fake:payload
37652     89/<- %ecx 4/r32/esp
37653 $test-compare-reg-with-reg:initialize-var1-name:
37654     # var1->name = "var1"
37655     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
37656     (copy-array Heap "var1" %eax)
37657 $test-compare-reg-with-reg:initialize-var1-register:
37658     # var1->register = "ecx"
37659     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
37660     (copy-array Heap "ecx" %eax)
37661 $test-compare-reg-with-reg:initialize-var2:
37662     # var var2/edx: (payload var)
37663     68/push 0/imm32/register
37664     68/push 0/imm32/register
37665     68/push 0/imm32/no-stack-offset
37666     68/push 1/imm32/block-depth
37667     ff 6/subop/push *(ecx+0x10)
37668     68/push 0x11/imm32/alloc-id:fake
37669     68/push 0/imm32/name
37670     68/push 0/imm32/name
37671     68/push 0x11/imm32/alloc-id:fake:payload
37672     89/<- %edx 4/r32/esp
37673 $test-compare-reg-with-reg:initialize-var2-name:
37674     # var2->name = "var2"
37675     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
37676     (copy-array Heap "var2" %eax)
37677 $test-compare-reg-with-reg:initialize-var2-register:
37678     # var2->register = "eax"
37679     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
37680     (copy-array Heap "eax" %eax)
37681 $test-compare-reg-with-reg:initialize-inouts:
37682     # var inouts/esi: (payload stmt-var) = [var2]
37683     68/push 0/imm32/is-deref:false
37684     68/push 0/imm32/next
37685     68/push 0/imm32/next
37686     52/push-edx/var2
37687     68/push 0x11/imm32/alloc-id:fake
37688     68/push 0x11/imm32/alloc-id:fake:payload
37689     89/<- %esi 4/r32/esp
37690     # inouts = [var1, var2]
37691     68/push 0/imm32/is-deref:false
37692     56/push-esi/next
37693     68/push 0x11/imm32/alloc-id:fake
37694     51/push-ecx/var1
37695     68/push 0x11/imm32/alloc-id:fake
37696     68/push 0x11/imm32/alloc-id:fake:payload
37697     89/<- %esi 4/r32/esp
37698 $test-compare-reg-with-reg:initialize-stmt:
37699     # var stmt/esi: (addr statement)
37700     68/push 0/imm32/next
37701     68/push 0/imm32/next
37702     68/push 0/imm32/outputs
37703     68/push 0/imm32/outputs
37704     56/push-esi/inouts
37705     68/push 0x11/imm32/alloc-id:fake
37706     68/push 0/imm32/operation
37707     68/push 0/imm32/operation
37708     68/push 1/imm32/tag:stmt1
37709     89/<- %esi 4/r32/esp
37710 $test-compare-reg-with-reg:initialize-stmt-operation:
37711     # stmt->operation = "compare"
37712     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
37713     (copy-array Heap "compare" %eax)
37714     # convert
37715     c7 0/subop/copy *Curr-block-depth 0/imm32
37716     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
37717     (flush _test-output-buffered-file)
37718 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
37724     # check output
37725     (check-next-stream-line-equal _test-output-stream "39/compare-> %ecx 0x00000000/r32" "F - test-compare-reg-with-reg")
37726     # . epilogue
37727     89/<- %esp 5/r32/ebp
37728     5d/pop-to-ebp
37729     c3/return
37730 
37731 test-compare-mem-with-reg:
37732     #   compare var1, var2/eax
37733     # =>
37734     #   39/compare *(ebp+___) 0/r32/eax
37735     #
37736     # . prologue
37737     55/push-ebp
37738     89/<- %ebp 4/r32/esp
37739     # setup
37740     (clear-stream _test-output-stream)
37741     (clear-stream $_test-output-buffered-file->buffer)
37742 $test-compare-mem-with-reg:initialize-type:
37743     # var type/ecx: (payload type-tree) = int
37744     68/push 0/imm32/right:null
37745     68/push 0/imm32/right:null
37746     68/push 0/imm32/left:unused
37747     68/push 1/imm32/value:int
37748     68/push 1/imm32/is-atom?:true
37749     68/push 0x11/imm32/alloc-id:fake:payload
37750     89/<- %ecx 4/r32/esp
37751 $test-compare-mem-with-reg:initialize-var1:
37752     # var var1/ecx: (payload var)
37753     68/push 0/imm32/register
37754     68/push 0/imm32/register
37755     68/push 8/imm32/stack-offset
37756     68/push 1/imm32/block-depth
37757     51/push-ecx
37758     68/push 0x11/imm32/alloc-id:fake
37759     68/push 0/imm32/name
37760     68/push 0/imm32/name
37761     68/push 0x11/imm32/alloc-id:fake:payload
37762     89/<- %ecx 4/r32/esp
37763 $test-compare-mem-with-reg:initialize-var1-name:
37764     # var1->name = "var1"
37765     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
37766     (copy-array Heap "var1" %eax)
37767 $test-compare-mem-with-reg:initialize-var2:
37768     # var var2/edx: (payload var)
37769     68/push 0/imm32/register
37770     68/push 0/imm32/register
37771     68/push 0/imm32/no-stack-offset
37772     68/push 1/imm32/block-depth
37773     ff 6/subop/push *(ecx+0x10)
37774     68/push 0x11/imm32/alloc-id:fake
37775     68/push 0/imm32/name
37776     68/push 0/imm32/name
37777     68/push 0x11/imm32/alloc-id:fake:payload
37778     89/<- %edx 4/r32/esp
37779 $test-compare-mem-with-reg:initialize-var2-name:
37780     # var2->name = "var2"
37781     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
37782     (copy-array Heap "var2" %eax)
37783 $test-compare-mem-with-reg:initialize-var2-register:
37784     # var2->register = "eax"
37785     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
37786     (copy-array Heap "eax" %eax)
37787 $test-compare-mem-with-reg:initialize-inouts:
37788     # var inouts/esi: (payload stmt-var) = [var2]
37789     68/push 0/imm32/is-deref:false
37790     68/push 0/imm32/next
37791     68/push 0/imm32/next
37792     52/push-edx/var2
37793     68/push 0x11/imm32/alloc-id:fake
37794     68/push 0x11/imm32/alloc-id:fake:payload
37795     89/<- %esi 4/r32/esp
37796     # inouts = [var1, var2]
37797     68/push 0/imm32/is-deref:false
37798     56/push-esi/next
37799     68/push 0x11/imm32/alloc-id:fake
37800     51/push-ecx/var1
37801     68/push 0x11/imm32/alloc-id:fake
37802     68/push 0x11/imm32/alloc-id:fake:payload
37803     89/<- %esi 4/r32/esp
37804 $test-compare-mem-with-reg:initialize-stmt:
37805     # var stmt/esi: (addr statement)
37806     68/push 0/imm32/next
37807     68/push 0/imm32/next
37808     68/push 0/imm32/outputs
37809     68/push 0/imm32/outputs
37810     56/push-esi/inouts
37811     68/push 0x11/imm32/alloc-id:fake
37812     68/push 0/imm32/operation
37813     68/push 0/imm32/operation
37814     68/push 1/imm32/tag:stmt1
37815     89/<- %esi 4/r32/esp
37816 $test-compare-mem-with-reg:initialize-stmt-operation:
37817     # stmt->operation = "compare"
37818     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
37819     (copy-array Heap "compare" %eax)
37820     # convert
37821     c7 0/subop/copy *Curr-block-depth 0/imm32
37822     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
37823     (flush _test-output-buffered-file)
37824 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
37830     # check output
37831     (check-next-stream-line-equal _test-output-stream "39/compare-> *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-mem-with-reg")
37832     # . epilogue
37833     89/<- %esp 5/r32/ebp
37834     5d/pop-to-ebp
37835     c3/return
37836 
37837 test-compare-reg-with-mem:
37838     #   compare var1/eax, var2
37839     # =>
37840     #   3b/compare<- *(ebp+___) 0/r32/eax
37841     #
37842     # . prologue
37843     55/push-ebp
37844     89/<- %ebp 4/r32/esp
37845     # setup
37846     (clear-stream _test-output-stream)
37847     (clear-stream $_test-output-buffered-file->buffer)
37848 $test-compare-reg-with-mem:initialize-type:
37849     # var type/ecx: (payload type-tree) = int
37850     68/push 0/imm32/right:null
37851     68/push 0/imm32/right:null
37852     68/push 0/imm32/left:unused
37853     68/push 1/imm32/value:int
37854     68/push 1/imm32/is-atom?:true
37855     68/push 0x11/imm32/alloc-id:fake:payload
37856     89/<- %ecx 4/r32/esp
37857 $test-compare-reg-with-mem:initialize-var1:
37858     # var var1/ecx: (payload var)
37859     68/push 0/imm32/register
37860     68/push 0/imm32/register
37861     68/push 0/imm32/no-stack-offset
37862     68/push 1/imm32/block-depth
37863     51/push-ecx
37864     68/push 0x11/imm32/alloc-id:fake
37865     68/push 0/imm32/name
37866     68/push 0/imm32/name
37867     68/push 0x11/imm32/alloc-id:fake:payload
37868     89/<- %ecx 4/r32/esp
37869 $test-compare-reg-with-mem:initialize-var1-name:
37870     # var1->name = "var1"
37871     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
37872     (copy-array Heap "var1" %eax)
37873 $test-compare-reg-with-mem:initialize-var1-register:
37874     # var1->register = "eax"
37875     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
37876     (copy-array Heap "eax" %eax)
37877 $test-compare-reg-with-mem:initialize-var2:
37878     # var var2/edx: (payload var)
37879     68/push 0/imm32/register
37880     68/push 0/imm32/register
37881     68/push 8/imm32/stack-offset
37882     68/push 1/imm32/block-depth
37883     ff 6/subop/push *(ecx+0x10)
37884     68/push 0x11/imm32/alloc-id:fake
37885     68/push 0/imm32/name
37886     68/push 0/imm32/name
37887     68/push 0x11/imm32/alloc-id:fake:payload
37888     89/<- %edx 4/r32/esp
37889 $test-compare-reg-with-mem:initialize-var2-name:
37890     # var2->name = "var2"
37891     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
37892     (copy-array Heap "var2" %eax)
37893 $test-compare-reg-with-mem:initialize-inouts:
37894     # var inouts/esi: (payload stmt-var) = [var2]
37895     68/push 0/imm32/is-deref:false
37896     68/push 0/imm32/next
37897     68/push 0/imm32/next
37898     52/push-edx/var2
37899     68/push 0x11/imm32/alloc-id:fake
37900     68/push 0x11/imm32/alloc-id:fake:payload
37901     89/<- %esi 4/r32/esp
37902     # inouts = [var1, var2]
37903     68/push 0/imm32/is-deref:false
37904     56/push-esi/next
37905     68/push 0x11/imm32/alloc-id:fake
37906     51/push-ecx/var1
37907     68/push 0x11/imm32/alloc-id:fake
37908     68/push 0x11/imm32/alloc-id:fake:payload
37909     89/<- %esi 4/r32/esp
37910 $test-compare-reg-with-mem:initialize-stmt:
37911     # var stmt/esi: (addr statement)
37912     68/push 0/imm32/next
37913     68/push 0/imm32/next
37914     68/push 0/imm32/outputs
37915     68/push 0/imm32/outputs
37916     56/push-esi/inouts
37917     68/push 0x11/imm32/alloc-id:fake
37918     68/push 0/imm32/operation
37919     68/push 0/imm32/operation
37920     68/push 1/imm32/tag:stmt1
37921     89/<- %esi 4/r32/esp
37922 $test-compare-reg-with-mem:initialize-stmt-operation:
37923     # stmt->operation = "compare"
37924     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
37925     (copy-array Heap "compare" %eax)
37926     # convert
37927     c7 0/subop/copy *Curr-block-depth 0/imm32
37928     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
37929     (flush _test-output-buffered-file)
37930 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
37936     # check output
37937     (check-next-stream-line-equal _test-output-stream "3b/compare<- *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-reg-with-mem")
37938     # . epilogue
37939     89/<- %esp 5/r32/ebp
37940     5d/pop-to-ebp
37941     c3/return
37942 
37943 test-compare-mem-with-literal:
37944     #   compare var1, 0x34
37945     # =>
37946     #   81 7/subop/compare *(ebp+___) 0x34/imm32
37947     #
37948     # . prologue
37949     55/push-ebp
37950     89/<- %ebp 4/r32/esp
37951     # setup
37952     (clear-stream _test-output-stream)
37953     (clear-stream $_test-output-buffered-file->buffer)
37954 $test-compare-mem-with-literal:initialize-type:
37955     # var type/ecx: (payload type-tree) = int
37956     68/push 0/imm32/right:null
37957     68/push 0/imm32/right:null
37958     68/push 0/imm32/left:unused
37959     68/push 1/imm32/value:int
37960     68/push 1/imm32/is-atom?:true
37961     68/push 0x11/imm32/alloc-id:fake:payload
37962     89/<- %ecx 4/r32/esp
37963 $test-compare-mem-with-literal:initialize-var1:
37964     # var var1/ecx: (payload var)
37965     68/push 0/imm32/register
37966     68/push 0/imm32/register
37967     68/push 8/imm32/stack-offset
37968     68/push 1/imm32/block-depth
37969     51/push-ecx
37970     68/push 0x11/imm32/alloc-id:fake
37971     68/push 0/imm32/name
37972     68/push 0/imm32/name
37973     68/push 0x11/imm32/alloc-id:fake:payload
37974     89/<- %ecx 4/r32/esp
37975 $test-compare-mem-with-literal:initialize-var1-name:
37976     # var1->name = "var1"
37977     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
37978     (copy-array Heap "var1" %eax)
37979 $test-compare-mem-with-literal:initialize-literal-type:
37980     # var type/edx: (payload type-tree) = literal
37981     68/push 0/imm32/right:null
37982     68/push 0/imm32/right:null
37983     68/push 0/imm32/left:unused
37984     68/push 0/imm32/value:literal
37985     68/push 1/imm32/is-atom?:true
37986     68/push 0x11/imm32/alloc-id:fake:payload
37987     89/<- %edx 4/r32/esp
37988 $test-compare-mem-with-literal:initialize-literal:
37989     # var l/edx: (payload var)
37990     68/push 0/imm32/register
37991     68/push 0/imm32/register
37992     68/push 0/imm32/no-stack-offset
37993     68/push 1/imm32/block-depth
37994     52/push-edx
37995     68/push 0x11/imm32/alloc-id:fake
37996     68/push 0/imm32/name
37997     68/push 0/imm32/name
37998     68/push 0x11/imm32/alloc-id:fake:payload
37999     89/<- %edx 4/r32/esp
38000 $test-compare-mem-with-literal:initialize-literal-value:
38001     # l->name = "0x34"
38002     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
38003     (copy-array Heap "0x34" %eax)
38004 $test-compare-mem-with-literal:initialize-inouts:
38005     # var inouts/esi: (payload stmt-var) = [l]
38006     68/push 0/imm32/is-deref:false
38007     68/push 0/imm32/next
38008     68/push 0/imm32/next
38009     52/push-edx/l
38010     68/push 0x11/imm32/alloc-id:fake
38011     68/push 0x11/imm32/alloc-id:fake:payload
38012     89/<- %esi 4/r32/esp
38013     # var inouts = (handle stmt-var) = [var1, var2]
38014     68/push 0/imm32/is-deref:false
38015     56/push-esi/next
38016     68/push 0x11/imm32/alloc-id:fake
38017     51/push-ecx/var1
38018     68/push 0x11/imm32/alloc-id:fake
38019     68/push 0x11/imm32/alloc-id:fake:payload
38020     89/<- %esi 4/r32/esp
38021 $test-compare-mem-with-literal:initialize-stmt:
38022     # var stmt/esi: (addr statement)
38023     68/push 0/imm32/next
38024     68/push 0/imm32/next
38025     68/push 0/imm32/outputs
38026     68/push 0/imm32/outputs
38027     56/push-esi/inouts
38028     68/push 0x11/imm32/alloc-id:fake
38029     68/push 0/imm32/operation
38030     68/push 0/imm32/operation
38031     68/push 1/imm32/tag:stmt1
38032     89/<- %esi 4/r32/esp
38033 $test-compare-mem-with-literal:initialize-stmt-operation:
38034     # stmt->operation = "compare"
38035     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
38036     (copy-array Heap "compare" %eax)
38037     # convert
38038     c7 0/subop/copy *Curr-block-depth 0/imm32
38039     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
38040     (flush _test-output-buffered-file)
38041 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
38047     # check output
38048     (check-next-stream-line-equal _test-output-stream "81 7/subop/compare *(ebp+0x00000008) 0x34/imm32" "F - test-compare-mem-with-literal")
38049     # . epilogue
38050     89/<- %esp 5/r32/ebp
38051     5d/pop-to-ebp
38052     c3/return
38053 
38054 test-compare-eax-with-literal:
38055     #   compare var1/eax 0x34
38056     # =>
38057     #   3d/compare-eax-with 0x34/imm32
38058     #
38059     # . prologue
38060     55/push-ebp
38061     89/<- %ebp 4/r32/esp
38062     # setup
38063     (clear-stream _test-output-stream)
38064     (clear-stream $_test-output-buffered-file->buffer)
38065 $test-compare-eax-with-literal:initialize-type:
38066     # var type/ecx: (payload type-tree) = int
38067     68/push 0/imm32/right:null
38068     68/push 0/imm32/right:null
38069     68/push 0/imm32/left:unused
38070     68/push 1/imm32/value:int
38071     68/push 1/imm32/is-atom?:true
38072     68/push 0x11/imm32/alloc-id:fake:payload
38073     89/<- %ecx 4/r32/esp
38074 $test-compare-eax-with-literal:initialize-var1:
38075     # var var1/ecx: (payload var)
38076     68/push 0/imm32/register
38077     68/push 0/imm32/register
38078     68/push 0/imm32/no-stack-offset
38079     68/push 1/imm32/block-depth
38080     51/push-ecx
38081     68/push 0x11/imm32/alloc-id:fake
38082     68/push 0/imm32/name
38083     68/push 0/imm32/name
38084     68/push 0x11/imm32/alloc-id:fake:payload
38085     89/<- %ecx 4/r32/esp
38086 $test-compare-eax-with-literal:initialize-var1-name:
38087     # var1->name = "var1"
38088     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
38089     (copy-array Heap "var1" %eax)
38090 $test-compare-eax-with-literal:initialize-var1-register:
38091     # v->register = "eax"
38092     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
38093     (copy-array Heap "eax" %eax)
38094 $test-compare-eax-with-literal:initialize-literal-type:
38095     # var type/edx: (payload type-tree) = literal
38096     68/push 0/imm32/right:null
38097     68/push 0/imm32/right:null
38098     68/push 0/imm32/left:unused
38099     68/push 0/imm32/value:literal
38100     68/push 1/imm32/is-atom?:true
38101     68/push 0x11/imm32/alloc-id:fake:payload
38102     89/<- %edx 4/r32/esp
38103 $test-compare-eax-with-literal:initialize-literal:
38104     # var l/edx: (payload var)
38105     68/push 0/imm32/register
38106     68/push 0/imm32/register
38107     68/push 0/imm32/no-stack-offset
38108     68/push 1/imm32/block-depth
38109     52/push-edx
38110     68/push 0x11/imm32/alloc-id:fake
38111     68/push 0/imm32/name
38112     68/push 0/imm32/name
38113     68/push 0x11/imm32/alloc-id:fake:payload
38114     89/<- %edx 4/r32/esp
38115 $test-compare-eax-with-literal:initialize-literal-value:
38116     # l->name = "0x34"
38117     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
38118     (copy-array Heap "0x34" %eax)
38119 $test-compare-eax-with-literal:initialize-inouts:
38120     # var inouts/esi: (payload stmt-var) = [l]
38121     68/push 0/imm32/is-deref:false
38122     68/push 0/imm32/next
38123     68/push 0/imm32/next
38124     52/push-edx/l
38125     68/push 0x11/imm32/alloc-id:fake
38126     68/push 0x11/imm32/alloc-id:fake:payload
38127     89/<- %esi 4/r32/esp
38128     # var inouts = (handle stmt-var) = [var1, var2]
38129     68/push 0/imm32/is-deref:false
38130     56/push-esi/next
38131     68/push 0x11/imm32/alloc-id:fake
38132     51/push-ecx/var1
38133     68/push 0x11/imm32/alloc-id:fake
38134     68/push 0x11/imm32/alloc-id:fake:payload
38135     89/<- %esi 4/r32/esp
38136 $test-compare-eax-with-literal:initialize-stmt:
38137     # var stmt/esi: (addr statement)
38138     68/push 0/imm32/next
38139     68/push 0/imm32/next
38140     68/push 0/imm32/outputs
38141     68/push 0/imm32/outputs
38142     56/push-esi/inouts
38143     68/push 0x11/imm32/alloc-id:fake
38144     68/push 0/imm32/operation
38145     68/push 0/imm32/operation
38146     68/push 1/imm32/tag:stmt1
38147     89/<- %esi 4/r32/esp
38148 $test-compare-eax-with-literal:initialize-stmt-operation:
38149     # stmt->operation = "compare"
38150     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
38151     (copy-array Heap "compare" %eax)
38152     # convert
38153     c7 0/subop/copy *Curr-block-depth 0/imm32
38154     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
38155     (flush _test-output-buffered-file)
38156 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
38162     # check output
38163     (check-next-stream-line-equal _test-output-stream "3d/compare-eax-with 0x34/imm32" "F - test-compare-eax-with-literal")
38164     # . epilogue
38165     89/<- %esp 5/r32/ebp
38166     5d/pop-to-ebp
38167     c3/return
38168 
38169 test-compare-reg-with-literal:
38170     #   compare var1/ecx 0x34
38171     # =>
38172     #   81 7/subop/compare %ecx 0x34/imm32
38173     #
38174     # . prologue
38175     55/push-ebp
38176     89/<- %ebp 4/r32/esp
38177     # setup
38178     (clear-stream _test-output-stream)
38179     (clear-stream $_test-output-buffered-file->buffer)
38180 $test-compare-reg-with-literal:initialize-type:
38181     # var type/ecx: (payload type-tree) = int
38182     68/push 0/imm32/right:null
38183     68/push 0/imm32/right:null
38184     68/push 0/imm32/left:unused
38185     68/push 1/imm32/value:int
38186     68/push 1/imm32/is-atom?:true
38187     68/push 0x11/imm32/alloc-id:fake:payload
38188     89/<- %ecx 4/r32/esp
38189 $test-compare-reg-with-literal:initialize-var1:
38190     # var var1/ecx: (payload var)
38191     68/push 0/imm32/register
38192     68/push 0/imm32/register
38193     68/push 0/imm32/no-stack-offset
38194     68/push 1/imm32/block-depth
38195     51/push-ecx
38196     68/push 0x11/imm32/alloc-id:fake
38197     68/push 0/imm32/name
38198     68/push 0/imm32/name
38199     68/push 0x11/imm32/alloc-id:fake:payload
38200     89/<- %ecx 4/r32/esp
38201 $test-compare-reg-with-literal:initialize-var1-name:
38202     # var1->name = "var1"
38203     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
38204     (copy-array Heap "var1" %eax)
38205 $test-compare-reg-with-literal:initialize-var1-register:
38206     # v->register = "ecx"
38207     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
38208     (copy-array Heap "ecx" %eax)
38209 $test-compare-reg-with-literal:initialize-literal-type:
38210     # var type/edx: (payload type-tree) = literal
38211     68/push 0/imm32/right:null
38212     68/push 0/imm32/right:null
38213     68/push 0/imm32/left:unused
38214     68/push 0/imm32/value:literal
38215     68/push 1/imm32/is-atom?:true
38216     68/push 0x11/imm32/alloc-id:fake:payload
38217     89/<- %edx 4/r32/esp
38218 $test-compare-reg-with-literal:initialize-literal:
38219     # var l/edx: (payload var)
38220     68/push 0/imm32/register
38221     68/push 0/imm32/register
38222     68/push 0/imm32/no-stack-offset
38223     68/push 1/imm32/block-depth
38224     52/push-edx
38225     68/push 0x11/imm32/alloc-id:fake
38226     68/push 0/imm32/name
38227     68/push 0/imm32/name
38228     68/push 0x11/imm32/alloc-id:fake:payload
38229     89/<- %edx 4/r32/esp
38230 $test-compare-reg-with-literal:initialize-literal-value:
38231     # l->name = "0x34"
38232     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
38233     (copy-array Heap "0x34" %eax)
38234 $test-compare-reg-with-literal:initialize-inouts:
38235     # var inouts/esi: (payload stmt-var) = [l]
38236     68/push 0/imm32/is-deref:false
38237     68/push 0/imm32/next
38238     68/push 0/imm32/next
38239     52/push-edx/l
38240     68/push 0x11/imm32/alloc-id:fake
38241     68/push 0x11/imm32/alloc-id:fake:payload
38242     89/<- %esi 4/r32/esp
38243     # var inouts = (handle stmt-var) = [var1, var2]
38244     68/push 0/imm32/is-deref:false
38245     56/push-esi/next
38246     68/push 0x11/imm32/alloc-id:fake
38247     51/push-ecx/var1
38248     68/push 0x11/imm32/alloc-id:fake
38249     68/push 0x11/imm32/alloc-id:fake:payload
38250     89/<- %esi 4/r32/esp
38251 $test-compare-reg-with-literal:initialize-stmt:
38252     # var stmt/esi: (addr statement)
38253     68/push 0/imm32/next
38254     68/push 0/imm32/next
38255     68/push 0/imm32/outputs
38256     68/push 0/imm32/outputs
38257     56/push-esi/inouts
38258     68/push 0x11/imm32/alloc-id:fake
38259     68/push 0/imm32/operation
38260     68/push 0/imm32/operation
38261     68/push 1/imm32/tag:stmt1
38262     89/<- %esi 4/r32/esp
38263 $test-compare-reg-with-literal:initialize-stmt-operation:
38264     # stmt->operation = "compare"
38265     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
38266     (copy-array Heap "compare" %eax)
38267     # convert
38268     c7 0/subop/copy *Curr-block-depth 0/imm32
38269     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
38270     (flush _test-output-buffered-file)
38271 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
38277     # check output
38278     (check-next-stream-line-equal _test-output-stream "81 7/subop/compare %ecx 0x34/imm32" "F - test-compare-reg-with-literal")
38279     # . epilogue
38280     89/<- %esp 5/r32/ebp
38281     5d/pop-to-ebp
38282     c3/return
38283 
38284 test-emit-subx-stmt-function-call:
38285     # Call a function on a variable on the stack.
38286     #   f foo
38287     # =>
38288     #   (f *(ebp-8))
38289     # (Changing the function name supports overloading in general, but here it
38290     # just serves to help disambiguate things.)
38291     #
38292     # There's a variable on the var stack as follows:
38293     #   name: 'foo'
38294     #   type: int
38295     #   stack-offset: -8
38296     #
38297     # There's nothing in primitives.
38298     #
38299     # We don't perform any checking here on the type of 'f'.
38300     #
38301     # . prologue
38302     55/push-ebp
38303     89/<- %ebp 4/r32/esp
38304     # setup
38305     (clear-stream _test-output-stream)
38306     (clear-stream $_test-output-buffered-file->buffer)
38307 $test-emit-subx-function-call:initialize-type:
38308     # var type/ecx: (payload type-tree) = int
38309     68/push 0/imm32/right:null
38310     68/push 0/imm32/right:null
38311     68/push 0/imm32/left:unused
38312     68/push 1/imm32/value:int
38313     68/push 1/imm32/is-atom?:true
38314     68/push 0x11/imm32/alloc-id:fake:payload
38315     89/<- %ecx 4/r32/esp
38316 $test-emit-subx-function-call:initialize-var:
38317     # var var-foo/ecx: (payload var) = var(type)
38318     68/push 0/imm32/no-register
38319     68/push 0/imm32/no-register
38320     68/push -8/imm32/stack-offset
38321     68/push 1/imm32/block-depth
38322     51/push-ecx/type
38323     68/push 0x11/imm32/alloc-id:fake
38324     68/push 0/imm32/name
38325     68/push 0/imm32/name
38326     68/push 0x11/imm32/alloc-id:fake:payload
38327     89/<- %ecx 4/r32/esp
38328 $test-emit-subx-function-call:initialize-var-name:
38329     # var-foo->name = "foo"
38330     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
38331     (copy-array Heap "foo" %eax)
38332 $test-emit-subx-function-call:initialize-stmt-var:
38333     # var operand/ebx: (payload stmt-var) = stmt-var(var-foo)
38334     68/push 0/imm32/is-deref:false
38335     68/push 0/imm32/next
38336     68/push 0/imm32/next
38337     51/push-ecx/var-foo
38338     68/push 0x11/imm32/alloc-id:fake
38339     68/push 0x11/imm32/alloc-id:fake:payload
38340     89/<- %ebx 4/r32/esp
38341 $test-emit-subx-function-call:initialize-stmt:
38342     # var stmt/esi: (addr statement)
38343     68/push 0/imm32/no-outputs
38344     68/push 0/imm32/no-outputs
38345     53/push-ebx/inouts
38346     68/push 0x11/imm32/alloc-id:fake
38347     68/push 0/imm32/operation
38348     68/push 0/imm32/operation
38349     68/push 1/imm32/tag
38350     89/<- %esi 4/r32/esp
38351 $test-emit-subx-function-call:initialize-stmt-operation:
38352     # stmt->operation = "f"
38353     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
38354     (copy-array Heap "f" %eax)
38355     # convert
38356     c7 0/subop/copy *Curr-block-depth 0/imm32
38357     (emit-subx-stmt _test-output-buffered-file %esi 0 0 Stderr 0)
38358     (flush _test-output-buffered-file)
38359 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
38365     # check output
38366     (check-next-stream-line-equal _test-output-stream "(f *(ebp+0xfffffff8))" "F - test-emit-subx-stmt-function-call")
38367     # . epilogue
38368     89/<- %esp 5/r32/ebp
38369     5d/pop-to-ebp
38370     c3/return
38371 
38372 test-emit-subx-stmt-function-call-with-literal-arg:
38373     # Call a function on a literal.
38374     #   f 0x34
38375     # =>
38376     #   (f2 0x34)
38377     #
38378     # . prologue
38379     55/push-ebp
38380     89/<- %ebp 4/r32/esp
38381     # setup
38382     (clear-stream _test-output-stream)
38383     (clear-stream $_test-output-buffered-file->buffer)
38384 $test-emit-subx-function-call-with-literal-arg:initialize-type:
38385     # var type/ecx: (payload type-tree) = int
38386     68/push 0/imm32/right:null
38387     68/push 0/imm32/right:null
38388     68/push 0/imm32/left:unused
38389     68/push 0/imm32/value:literal
38390     68/push 1/imm32/is-atom?:true
38391     68/push 0x11/imm32/alloc-id:fake:payload
38392     89/<- %ecx 4/r32/esp
38393 $test-emit-subx-function-call-with-literal-arg:initialize-var:
38394     # var var-foo/ecx: (payload var) = var(lit)
38395     68/push 0/imm32/no-register
38396     68/push 0/imm32/no-register
38397     68/push 0/imm32/no-stack-offset
38398     68/push 1/imm32/block-depth
38399     51/push-ecx/type
38400     68/push 0x11/imm32/alloc-id:fake
38401     68/push 0/imm32/name
38402     68/push 0/imm32/name
38403     68/push 0x11/imm32/alloc-id:fake:payload
38404     89/<- %ecx 4/r32/esp
38405 $test-emit-subx-function-call-with-literal-arg:initialize-var-name:
38406     # var-foo->name = "0x34"
38407     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
38408     (copy-array Heap "0x34" %eax)
38409 $test-emit-subx-function-call-with-literal-arg:initialize-stmt-var:
38410     # var operand/ebx: (payload stmt-var) = stmt-var(var-foo)
38411     68/push 0/imm32/is-deref:false
38412     68/push 0/imm32/next
38413     68/push 0/imm32/next
38414     51/push-ecx/var-foo
38415     68/push 0x11/imm32/alloc-id:fake
38416     68/push 0x11/imm32/alloc-id:fake:payload
38417     89/<- %ebx 4/r32/esp
38418 $test-emit-subx-function-call-with-literal-arg:initialize-stmt:
38419     # var stmt/esi: (addr statement)
38420     68/push 0/imm32/no-outputs
38421     68/push 0/imm32/no-outputs
38422     53/push-ebx/inouts
38423     68/push 0x11/imm32/alloc-id:fake
38424     68/push 0/imm32/operation
38425     68/push 0/imm32/operation
38426     68/push 1/imm32/tag
38427     89/<- %esi 4/r32/esp
38428 $test-emit-subx-function-call-with-literal-arg:initialize-stmt-operation:
38429     # stmt->operation = "f"
38430     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
38431     (copy-array Heap "f" %eax)
38432     # convert
38433     c7 0/subop/copy *Curr-block-depth 0/imm32
38434     (emit-subx-stmt _test-output-buffered-file %esi 0 %ebx 0 Stderr 0)
38435     (flush _test-output-buffered-file)
38436 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
38442     # check output
38443     (check-next-stream-line-equal _test-output-stream "(f 0x34)" "F - test-emit-subx-stmt-function-call-with-literal-arg")
38444     # . epilogue
38445     89/<- %esp 5/r32/ebp
38446     5d/pop-to-ebp
38447     c3/return
38448 
38449 emit-indent:  # out: (addr buffered-file), n: int
38450     # . prologue
38451     55/push-ebp
38452     89/<- %ebp 4/r32/esp
38453     # . save registers
38454     50/push-eax
38455     # var i/eax: int = n
38456     8b/-> *(ebp+0xc) 0/r32/eax
38457     {
38458       # if (i <= 0) break
38459       3d/compare-eax-with 0/imm32
38460       7e/jump-if-<= break/disp8
38461       (write-buffered *(ebp+8) "  ")
38462       48/decrement-eax
38463       eb/jump loop/disp8
38464     }
38465 $emit-indent:end:
38466     # . restore registers
38467     58/pop-to-eax
38468     # . epilogue
38469     89/<- %esp 5/r32/ebp
38470     5d/pop-to-ebp
38471     c3/return
38472 
38473 emit-subx-prologue:  # out: (addr buffered-file)
38474     # . prologue
38475     55/push-ebp
38476     89/<- %ebp 4/r32/esp
38477     #
38478     (write-buffered *(ebp+8) "  # . prologue\n")
38479     (write-buffered *(ebp+8) "  55/push-ebp\n")
38480     (write-buffered *(ebp+8) "  89/<- %ebp 4/r32/esp\n")
38481 $emit-subx-prologue:end:
38482     # . epilogue
38483     89/<- %esp 5/r32/ebp
38484     5d/pop-to-ebp
38485     c3/return
38486 
38487 emit-subx-epilogue:  # out: (addr buffered-file)
38488     # . prologue
38489     55/push-ebp
38490     89/<- %ebp 4/r32/esp
38491     #
38492     (write-buffered *(ebp+8) "  # . epilogue\n")
38493     (write-buffered *(ebp+8) "  89/<- %esp 5/r32/ebp\n")
38494     (write-buffered *(ebp+8) "  5d/pop-to-ebp\n")
38495     (write-buffered *(ebp+8) "  c3/return\n")
38496 $emit-subx-epilogue:end:
38497     # . epilogue
38498     89/<- %esp 5/r32/ebp
38499     5d/pop-to-ebp
38500     c3/return